From a5000fbbc56ab253494f928cb4836873fcef2287 Mon Sep 17 00:00:00 2001
From: Ludy <Ludy87@users.noreply.github.com>
Date: Sun, 21 Apr 2024 13:15:18 +0200
Subject: [PATCH] UI: settings show/hide update display (#1072)

* UI: settings show/hide update display

This PR replaces the PR #1003

In this PR, the visual for available update is added to the foreground.

There are new settings to generally show/hide the update display, and only administrators receive the update display.

* change to `Bean`

* Update AppUpdateShowService.java

* add update message

* revision service

* change shouldShow

* Update githubVersion.js

* rm folder

* Update AppUpdateService.java
---
 README.md                                     |  2 +
 .../SPDF/config/AppUpdateService.java         | 25 ++++++++++
 .../SPDF/config/ShowAdminInterface.java       |  7 +++
 .../config/security/AppUpdateAuthService.java | 46 +++++++++++++++++++
 .../controller/web/OtherWebController.java    |  1 +
 .../SPDF/model/ApplicationProperties.java     | 22 +++++++++
 src/main/resources/messages_ar_AR.properties  |  1 +
 src/main/resources/messages_bg_BG.properties  |  1 +
 src/main/resources/messages_ca_CA.properties  |  1 +
 src/main/resources/messages_de_DE.properties  |  1 +
 src/main/resources/messages_el_GR.properties  |  1 +
 src/main/resources/messages_en_GB.properties  |  1 +
 src/main/resources/messages_en_US.properties  |  1 +
 src/main/resources/messages_es_ES.properties  |  1 +
 src/main/resources/messages_eu_ES.properties  |  1 +
 src/main/resources/messages_fr_FR.properties  |  1 +
 src/main/resources/messages_hi_IN.properties  |  1 +
 src/main/resources/messages_hu_HU.properties  |  1 +
 src/main/resources/messages_id_ID.properties  |  1 +
 src/main/resources/messages_it_IT.properties  |  1 +
 src/main/resources/messages_ja_JP.properties  |  1 +
 src/main/resources/messages_ko_KR.properties  |  1 +
 src/main/resources/messages_nl_NL.properties  |  1 +
 src/main/resources/messages_pl_PL.properties  |  1 +
 src/main/resources/messages_pt_BR.properties  |  1 +
 src/main/resources/messages_pt_PT.properties  |  1 +
 src/main/resources/messages_ro_RO.properties  |  1 +
 src/main/resources/messages_ru_RU.properties  |  1 +
 .../resources/messages_sr_LATN_RS.properties  |  1 +
 src/main/resources/messages_sv_SE.properties  |  1 +
 src/main/resources/messages_tr_TR.properties  |  1 +
 src/main/resources/messages_uk_UA.properties  |  1 +
 src/main/resources/messages_zh_CN.properties  |  1 +
 src/main/resources/messages_zh_TW.properties  |  1 +
 src/main/resources/settings.yml.template      |  4 +-
 src/main/resources/static/css/home.css        | 35 ++++++++++++++
 src/main/resources/static/images/update.svg   |  1 +
 src/main/resources/static/js/githubVersion.js | 24 +++++++++-
 src/main/resources/static/js/homecard.js      |  6 +++
 .../resources/templates/fragments/navbar.html |  5 +-
 src/main/resources/templates/home.html        |  9 ++++
 41 files changed, 210 insertions(+), 5 deletions(-)
 create mode 100644 src/main/java/stirling/software/SPDF/config/AppUpdateService.java
 create mode 100644 src/main/java/stirling/software/SPDF/config/ShowAdminInterface.java
 create mode 100644 src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java
 create mode 100644 src/main/resources/static/images/update.svg

diff --git a/README.md b/README.md
index d7d2e1aa..5249e3cc 100644
--- a/README.md
+++ b/README.md
@@ -225,6 +225,8 @@ system:
   defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
   googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
   customStaticFilePath: '/customFiles/static/' # Directory path for custom static files
+  showUpdate: true # see when a new update is available
+  showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
 
 #ui:
 #  appName: exampleAppName # Application's visible name
diff --git a/src/main/java/stirling/software/SPDF/config/AppUpdateService.java b/src/main/java/stirling/software/SPDF/config/AppUpdateService.java
new file mode 100644
index 00000000..7c7a9a49
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/config/AppUpdateService.java
@@ -0,0 +1,25 @@
+package stirling.software.SPDF.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Service;
+
+import stirling.software.SPDF.model.ApplicationProperties;
+
+@Service
+class AppUpdateService {
+
+    @Autowired private ApplicationProperties applicationProperties;
+
+    @Autowired(required = false)
+    ShowAdminInterface showAdmin;
+
+    @Bean(name = "shouldShow")
+    @Scope("request")
+    public boolean shouldShow() {
+        boolean showUpdate = applicationProperties.getSystem().getShowUpdate();
+        boolean showAdminResult = (showAdmin != null) ? showAdmin.getShowUpdateOnlyAdmins() : true;
+        return showUpdate && showAdminResult;
+    }
+}
diff --git a/src/main/java/stirling/software/SPDF/config/ShowAdminInterface.java b/src/main/java/stirling/software/SPDF/config/ShowAdminInterface.java
new file mode 100644
index 00000000..e49376e2
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/config/ShowAdminInterface.java
@@ -0,0 +1,7 @@
+package stirling.software.SPDF.config;
+
+public interface ShowAdminInterface {
+    default boolean getShowUpdateOnlyAdmins() {
+        return true;
+    }
+}
diff --git a/src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java b/src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java
new file mode 100644
index 00000000..0da07c61
--- /dev/null
+++ b/src/main/java/stirling/software/SPDF/config/security/AppUpdateAuthService.java
@@ -0,0 +1,46 @@
+package stirling.software.SPDF.config.security;
+
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Service;
+
+import stirling.software.SPDF.config.ShowAdminInterface;
+import stirling.software.SPDF.model.ApplicationProperties;
+import stirling.software.SPDF.model.User;
+import stirling.software.SPDF.repository.UserRepository;
+
+@Service
+class AppUpdateAuthService implements ShowAdminInterface {
+
+    @Autowired private UserRepository userRepository;
+    @Autowired private ApplicationProperties applicationProperties;
+
+    public boolean getShowUpdateOnlyAdmins() {
+        boolean showUpdate = applicationProperties.getSystem().getShowUpdate();
+        if (!showUpdate) {
+            return showUpdate;
+        }
+
+        boolean showUpdateOnlyAdmin = applicationProperties.getSystem().getShowUpdateOnlyAdmin();
+
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+        if (authentication == null || !authentication.isAuthenticated()) {
+            return !showUpdateOnlyAdmin;
+        }
+
+        if (authentication.getName().equalsIgnoreCase("anonymousUser")) {
+            return !showUpdateOnlyAdmin;
+        }
+
+        Optional<User> user = userRepository.findByUsername(authentication.getName());
+        if (user.isPresent() && showUpdateOnlyAdmin) {
+            return "ROLE_ADMIN".equals(user.get().getRolesAsString());
+        }
+
+        return showUpdate;
+    }
+}
diff --git a/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java b/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java
index b93a89e4..b373d17a 100644
--- a/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java
+++ b/src/main/java/stirling/software/SPDF/controller/web/OtherWebController.java
@@ -17,6 +17,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
 @Controller
 @Tag(name = "Misc", description = "Miscellaneous APIs")
 public class OtherWebController {
+
     @GetMapping("/compress-pdf")
     @Hidden
     public String compressPdfForm(Model model) {
diff --git a/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java b/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java
index a41d641c..1a2aeaec 100644
--- a/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java
+++ b/src/main/java/stirling/software/SPDF/model/ApplicationProperties.java
@@ -210,6 +210,24 @@ public class ApplicationProperties {
         private String rootURIPath;
         private String customStaticFilePath;
         private Integer maxFileSize;
+        private boolean showUpdate;
+        private Boolean showUpdateOnlyAdmin;
+
+        public boolean getShowUpdateOnlyAdmin() {
+            return showUpdateOnlyAdmin;
+        }
+
+        public void setShowUpdateOnlyAdmin(boolean showUpdateOnlyAdmin) {
+            this.showUpdateOnlyAdmin = showUpdateOnlyAdmin;
+        }
+
+        public boolean getShowUpdate() {
+            return showUpdate;
+        }
+
+        public void setShowUpdate(boolean showUpdate) {
+            this.showUpdate = showUpdate;
+        }
 
         private Boolean enableAlphaFunctionality;
 
@@ -275,6 +293,10 @@ public class ApplicationProperties {
                     + maxFileSize
                     + ", enableAlphaFunctionality="
                     + enableAlphaFunctionality
+                    + ", showUpdate="
+                    + showUpdate
+                    + ", showUpdateOnlyAdmin="
+                    + showUpdateOnlyAdmin
                     + "]";
         }
     }
diff --git a/src/main/resources/messages_ar_AR.properties b/src/main/resources/messages_ar_AR.properties
index 44329a7b..ac90792a 100644
--- a/src/main/resources/messages_ar_AR.properties
+++ b/src/main/resources/messages_ar_AR.properties
@@ -112,6 +112,7 @@ navbar.settings=إعدادات
 #############
 settings.title=الإعدادات
 settings.update=التحديث متاح
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=إصدار التطبيق:
 settings.downloadOption.title=تحديد خيار التنزيل (للتنزيلات ذات الملف الواحد غير المضغوط):
 settings.downloadOption.1=فتح في نفس النافذة
diff --git a/src/main/resources/messages_bg_BG.properties b/src/main/resources/messages_bg_BG.properties
index 71983955..6262d46d 100644
--- a/src/main/resources/messages_bg_BG.properties
+++ b/src/main/resources/messages_bg_BG.properties
@@ -112,6 +112,7 @@ navbar.settings=Настройки
 #############
 settings.title=Настройки
 settings.update=Налична актуализация
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Версия на приложението:
 settings.downloadOption.title=Изберете опция за изтегляне (за изтегляния на един файл без да е архивиран):
 settings.downloadOption.1=Отваряне в същия прозорец
diff --git a/src/main/resources/messages_ca_CA.properties b/src/main/resources/messages_ca_CA.properties
index 1c5fcea3..6071b16b 100644
--- a/src/main/resources/messages_ca_CA.properties
+++ b/src/main/resources/messages_ca_CA.properties
@@ -112,6 +112,7 @@ navbar.settings=Opcions
 #############
 settings.title=Opcions
 settings.update=Actualització Disponible
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Versió App:
 settings.downloadOption.title=Trieu l'opció de descàrrega (per a descàrregues d'un sol fitxer no zip):
 settings.downloadOption.1=Obre mateixa finestra
diff --git a/src/main/resources/messages_de_DE.properties b/src/main/resources/messages_de_DE.properties
index 57ea05a1..729597be 100644
--- a/src/main/resources/messages_de_DE.properties
+++ b/src/main/resources/messages_de_DE.properties
@@ -112,6 +112,7 @@ navbar.settings=Einstellungen
 #############
 settings.title=Einstellungen
 settings.update=Update verfügbar
+settings.updateAvailable={0} ist die aktuelle installierte Version. Eine neue Version ({1}) ist verfügbar.
 settings.appVersion=App-Version:
 settings.downloadOption.title=Download-Option wählen (für einzelne Dateien, die keine Zip-Downloads sind):
 settings.downloadOption.1=Im selben Fenster öffnen
diff --git a/src/main/resources/messages_el_GR.properties b/src/main/resources/messages_el_GR.properties
index dac14ac7..93ab31e2 100644
--- a/src/main/resources/messages_el_GR.properties
+++ b/src/main/resources/messages_el_GR.properties
@@ -112,6 +112,7 @@ navbar.settings=Ρυθμίσεις
 #############
 settings.title=Ρυθμίσεις
 settings.update=Υπάρχει διαθέσιμη ενημέρωση
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Έκδοση εφαρμογής:
 settings.downloadOption.title=Επιλέξετε την επιλογή λήψης (Για λήψεις μεμονωμένων αρχείων χωρίς zip):
 settings.downloadOption.1=Άνοιγμα στο ίδιο παράθυρο
diff --git a/src/main/resources/messages_en_GB.properties b/src/main/resources/messages_en_GB.properties
index bae8f923..30bcb9fd 100644
--- a/src/main/resources/messages_en_GB.properties
+++ b/src/main/resources/messages_en_GB.properties
@@ -112,6 +112,7 @@ navbar.settings=Settings
 #############
 settings.title=Settings
 settings.update=Update available
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=App Version:
 settings.downloadOption.title=Choose download option (For single file non zip downloads):
 settings.downloadOption.1=Open in same window
diff --git a/src/main/resources/messages_en_US.properties b/src/main/resources/messages_en_US.properties
index 1126d0ce..3f0c7afb 100644
--- a/src/main/resources/messages_en_US.properties
+++ b/src/main/resources/messages_en_US.properties
@@ -112,6 +112,7 @@ navbar.settings=Settings
 #############
 settings.title=Settings
 settings.update=Update available
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=App Version:
 settings.downloadOption.title=Choose download option (For single file non zip downloads):
 settings.downloadOption.1=Open in same window
diff --git a/src/main/resources/messages_es_ES.properties b/src/main/resources/messages_es_ES.properties
index 0da4273f..bdb42a94 100644
--- a/src/main/resources/messages_es_ES.properties
+++ b/src/main/resources/messages_es_ES.properties
@@ -112,6 +112,7 @@ navbar.settings=Configuración
 #############
 settings.title=Configuración
 settings.update=Actualización disponible
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Versión de la aplicación:
 settings.downloadOption.title=Elegir la opción de descarga (para descargas de un solo archivo sin ZIP):
 settings.downloadOption.1=Abrir en la misma ventana
diff --git a/src/main/resources/messages_eu_ES.properties b/src/main/resources/messages_eu_ES.properties
index ec20aa7f..1f8f6b6d 100644
--- a/src/main/resources/messages_eu_ES.properties
+++ b/src/main/resources/messages_eu_ES.properties
@@ -112,6 +112,7 @@ navbar.settings=Ezarpenak
 #############
 settings.title=Ezarpenak
 settings.update=Eguneratze eskuragarria
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Aplikazioaren bertsioa:
 settings.downloadOption.title=Hautatu deskargatzeko aukera (fitxategi bakarra deskargatzeko ZIP gabe):
 settings.downloadOption.1=Ireki leiho berean
diff --git a/src/main/resources/messages_fr_FR.properties b/src/main/resources/messages_fr_FR.properties
index 23578dcc..3aa55d09 100644
--- a/src/main/resources/messages_fr_FR.properties
+++ b/src/main/resources/messages_fr_FR.properties
@@ -112,6 +112,7 @@ navbar.settings=Paramètres
 #############
 settings.title=Paramètres
 settings.update=Mise à jour disponible
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Version de l’application :
 settings.downloadOption.title=Choisissez l’option de téléchargement (pour les téléchargements à fichier unique non ZIP) :
 settings.downloadOption.1=Ouvrir dans la même fenêtre
diff --git a/src/main/resources/messages_hi_IN.properties b/src/main/resources/messages_hi_IN.properties
index 898e223f..b660d678 100644
--- a/src/main/resources/messages_hi_IN.properties
+++ b/src/main/resources/messages_hi_IN.properties
@@ -112,6 +112,7 @@ navbar.settings=सेटिंग्स
 #############
 settings.title=सेटिंग्स
 settings.update=अपडेट उपलब्ध है
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=ऐप संस्करण:
 settings.downloadOption.title=डाउनलोड विकल्प चुनें (एकल फ़ाइल गैर-ज़िप डाउनलोड के लिए):
 settings.downloadOption.1=एक ही विंडो में खोलें
diff --git a/src/main/resources/messages_hu_HU.properties b/src/main/resources/messages_hu_HU.properties
index 03f7f2b3..c9a4957b 100644
--- a/src/main/resources/messages_hu_HU.properties
+++ b/src/main/resources/messages_hu_HU.properties
@@ -112,6 +112,7 @@ navbar.settings=Beállítások
 #############
 settings.title=Beállítások
 settings.update=Frisítés elérhető
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=App Verzió:
 settings.downloadOption.title=Válassza ki a letöltési lehetőséget (Egyetlen fájl esetén a nem tömörített letöltésekhez):
 settings.downloadOption.1=Nyissa meg ugyanabban az ablakban
diff --git a/src/main/resources/messages_id_ID.properties b/src/main/resources/messages_id_ID.properties
index 697bb17b..3cbcc872 100644
--- a/src/main/resources/messages_id_ID.properties
+++ b/src/main/resources/messages_id_ID.properties
@@ -112,6 +112,7 @@ navbar.settings=Pengaturan
 #############
 settings.title=Pengaturan
 settings.update=Pembaruan tersedia
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Versi Aplikasi:
 settings.downloadOption.title=Pilih opsi unduhan (Untuk unduhan berkas tunggal non zip):
 settings.downloadOption.1=Buka di jendela yang sama
diff --git a/src/main/resources/messages_it_IT.properties b/src/main/resources/messages_it_IT.properties
index 7b14e61f..140a27f7 100644
--- a/src/main/resources/messages_it_IT.properties
+++ b/src/main/resources/messages_it_IT.properties
@@ -112,6 +112,7 @@ navbar.settings=Impostazioni
 #############
 settings.title=Impostazioni
 settings.update=Aggiornamento disponibile
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Versione App:
 settings.downloadOption.title=Scegli opzione di download (Per file singoli non compressi):
 settings.downloadOption.1=Apri in questa finestra
diff --git a/src/main/resources/messages_ja_JP.properties b/src/main/resources/messages_ja_JP.properties
index b4260c5a..fed17883 100644
--- a/src/main/resources/messages_ja_JP.properties
+++ b/src/main/resources/messages_ja_JP.properties
@@ -112,6 +112,7 @@ navbar.settings=設定
 #############
 settings.title=設定
 settings.update=利用可能なアップデート
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Appバージョン:
 settings.downloadOption.title=ダウンロードオプション (zip以外の単一ファイル):
 settings.downloadOption.1=同じウィンドウで開く
diff --git a/src/main/resources/messages_ko_KR.properties b/src/main/resources/messages_ko_KR.properties
index d78d7159..3b1d3441 100644
--- a/src/main/resources/messages_ko_KR.properties
+++ b/src/main/resources/messages_ko_KR.properties
@@ -112,6 +112,7 @@ navbar.settings=설정
 #############
 settings.title=설정
 settings.update=업데이트 가능
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=앱 버전:
 settings.downloadOption.title=다운로드 옵션 선택 (zip 파일이 아닌 단일 파일 다운로드 시):
 settings.downloadOption.1=현재 창에서 열기
diff --git a/src/main/resources/messages_nl_NL.properties b/src/main/resources/messages_nl_NL.properties
index 38bdfdf0..e5668210 100644
--- a/src/main/resources/messages_nl_NL.properties
+++ b/src/main/resources/messages_nl_NL.properties
@@ -112,6 +112,7 @@ navbar.settings=Instellingen
 #############
 settings.title=Instellingen
 settings.update=Update beschikbaar
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=App versie:
 settings.downloadOption.title=Kies download optie (Voor enkelvoudige bestanddownloads zonder zip):
 settings.downloadOption.1=Open in hetzelfde venster
diff --git a/src/main/resources/messages_pl_PL.properties b/src/main/resources/messages_pl_PL.properties
index 7f72cc23..c94f72cb 100644
--- a/src/main/resources/messages_pl_PL.properties
+++ b/src/main/resources/messages_pl_PL.properties
@@ -112,6 +112,7 @@ navbar.settings=Ustawienia
 #############
 settings.title=Ustawienia
 settings.update=Dostępna aktualizacja
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Wersia aplikacji:
 settings.downloadOption.title=Wybierz opcję pobierania (w przypadku pobierania pojedynczych plików innych niż ZIP):
 settings.downloadOption.1=Otwórz w tym samym oknie
diff --git a/src/main/resources/messages_pt_BR.properties b/src/main/resources/messages_pt_BR.properties
index 5a8d3d1f..b03402be 100644
--- a/src/main/resources/messages_pt_BR.properties
+++ b/src/main/resources/messages_pt_BR.properties
@@ -112,6 +112,7 @@ navbar.settings=Configurações
 #############
 settings.title=Configurações
 settings.update=Atualização disponível
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Versão do aplicativo:
 settings.downloadOption.title=Escolha a opção de download (para downloads não compactados de arquivo único):
 settings.downloadOption.1=Abrir na mesma janela
diff --git a/src/main/resources/messages_pt_PT.properties b/src/main/resources/messages_pt_PT.properties
index 4abeed7f..c1662afe 100644
--- a/src/main/resources/messages_pt_PT.properties
+++ b/src/main/resources/messages_pt_PT.properties
@@ -112,6 +112,7 @@ navbar.settings=Configurações
 #############
 settings.title=Configurações
 settings.update=Atualização disponível
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Versão da aplicação:
 settings.downloadOption.title=Escolha a opção de download (para downloads não compactados de ficheiro único):
 settings.downloadOption.1=Abrir na mesma janela
diff --git a/src/main/resources/messages_ro_RO.properties b/src/main/resources/messages_ro_RO.properties
index 7edcc2d2..949f34cf 100644
--- a/src/main/resources/messages_ro_RO.properties
+++ b/src/main/resources/messages_ro_RO.properties
@@ -112,6 +112,7 @@ navbar.settings=Setări
 #############
 settings.title=Setări
 settings.update=Actualizare disponibilă
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Versiune aplicație:
 settings.downloadOption.title=Alege opțiunea de descărcare (pentru descărcarea unui singur fișier non-zip):
 settings.downloadOption.1=Deschide în aceeași fereastră
diff --git a/src/main/resources/messages_ru_RU.properties b/src/main/resources/messages_ru_RU.properties
index b0d5cfc7..3d20fc0b 100644
--- a/src/main/resources/messages_ru_RU.properties
+++ b/src/main/resources/messages_ru_RU.properties
@@ -112,6 +112,7 @@ navbar.settings=Настройки
 #############
 settings.title=Настройки
 settings.update=Доступно обновление
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Версия приложения:
 settings.downloadOption.title=Выберите вариант загрузки (для загрузки одного файла без zip):
 settings.downloadOption.1=Открыть в том же окне
diff --git a/src/main/resources/messages_sr_LATN_RS.properties b/src/main/resources/messages_sr_LATN_RS.properties
index db5499bc..7cdd2f24 100644
--- a/src/main/resources/messages_sr_LATN_RS.properties
+++ b/src/main/resources/messages_sr_LATN_RS.properties
@@ -112,6 +112,7 @@ navbar.settings=Podešavanja
 #############
 settings.title=Podešavanja
 settings.update=Dostupno ažuriranje
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Verzija aplikacije:
 settings.downloadOption.title=Odaberite opciju preuzimanja (Za preuzimanje pojedinačnih fajlova bez zip formata):
 settings.downloadOption.1=Otvori u istom prozoru
diff --git a/src/main/resources/messages_sv_SE.properties b/src/main/resources/messages_sv_SE.properties
index a5d7e5f2..afa34270 100644
--- a/src/main/resources/messages_sv_SE.properties
+++ b/src/main/resources/messages_sv_SE.properties
@@ -112,6 +112,7 @@ navbar.settings=Inställningar
 #############
 settings.title=Inställningar
 settings.update=Uppdatering tillgänglig
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Appversion:
 settings.downloadOption.title=Välj nedladdningsalternativ (för nedladdning av en fil utan zip):
 settings.downloadOption.1=Öppnas i samma fönster
diff --git a/src/main/resources/messages_tr_TR.properties b/src/main/resources/messages_tr_TR.properties
index cb7cbb07..2ec0bd6b 100644
--- a/src/main/resources/messages_tr_TR.properties
+++ b/src/main/resources/messages_tr_TR.properties
@@ -112,6 +112,7 @@ navbar.settings=Ayarlar
 #############
 settings.title=Ayarlar
 settings.update=Güncelleme mevcut
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Uygulama Sürümü:
 settings.downloadOption.title=İndirme seçeneği seçin (Zip olmayan tek dosya indirmeler için):
 settings.downloadOption.1=Aynı pencerede aç
diff --git a/src/main/resources/messages_uk_UA.properties b/src/main/resources/messages_uk_UA.properties
index 8016ebd7..8a77d064 100644
--- a/src/main/resources/messages_uk_UA.properties
+++ b/src/main/resources/messages_uk_UA.properties
@@ -112,6 +112,7 @@ navbar.settings=Налаштування
 #############
 settings.title=Налаштування
 settings.update=Доступне оновлення
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=Версія додатку:
 settings.downloadOption.title=Виберіть варіант завантаження (для завантаження одного файлу без zip):
 settings.downloadOption.1=Відкрити в тому ж вікні
diff --git a/src/main/resources/messages_zh_CN.properties b/src/main/resources/messages_zh_CN.properties
index f1fb4ced..f10f3930 100644
--- a/src/main/resources/messages_zh_CN.properties
+++ b/src/main/resources/messages_zh_CN.properties
@@ -112,6 +112,7 @@ navbar.settings=设置
 #############
 settings.title=设置
 settings.update=可更新
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=应用程序版本:
 settings.downloadOption.title=选择下载选项(单个文件非压缩文件):
 settings.downloadOption.1=在同一窗口打开
diff --git a/src/main/resources/messages_zh_TW.properties b/src/main/resources/messages_zh_TW.properties
index b2d09e10..c2cfbadb 100644
--- a/src/main/resources/messages_zh_TW.properties
+++ b/src/main/resources/messages_zh_TW.properties
@@ -112,6 +112,7 @@ navbar.settings=設定
 #############
 settings.title=設定
 settings.update=有更新可用
+settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
 settings.appVersion=應用版本:
 settings.downloadOption.title=選擇下載選項(對於單一檔案非壓縮下載):
 settings.downloadOption.1=在同一視窗中開啟
diff --git a/src/main/resources/settings.yml.template b/src/main/resources/settings.yml.template
index 0a326e17..b3d6e954 100644
--- a/src/main/resources/settings.yml.template
+++ b/src/main/resources/settings.yml.template
@@ -12,7 +12,9 @@ system:
   defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
   googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
   enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
-  
+  showUpdate: true # see when a new update is available
+  showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
+
 #ui:
 #  appName: exampleAppName # Application's visible name
 #  homeDescription: I am a description # Short description or tagline shown on homepage.
diff --git a/src/main/resources/static/css/home.css b/src/main/resources/static/css/home.css
index d975dd79..ff8d1cf7 100644
--- a/src/main/resources/static/css/home.css
+++ b/src/main/resources/static/css/home.css
@@ -89,3 +89,38 @@
 .jumbotron {
   padding: 3rem 3rem; /* Reduce vertical padding */
 }
+
+.lookatme {
+  opacity: 1;
+  position: relative;
+  display: inline-block;
+}
+
+.lookatme::after {
+  color: #e33100;
+  text-shadow: 0 0 5px #e33100;
+  /* in the html, the data-lookatme-text attribute must */
+  /* contain the same text as the .lookatme element */
+  content: attr(data-lookatme-text);
+  padding: inherit;
+  position: absolute;
+  inset: 0 0 0 0;
+  z-index: 1;
+  /* 20 steps / 2 seconds = 10fps */
+  -webkit-animation: 2s infinite Pulse steps(20);
+  animation: 2s infinite Pulse steps(20);
+}
+
+@keyframes Pulse {
+  from {
+    opacity: 0;
+  }
+
+  50% {
+    opacity: 1;
+  }
+
+  to {
+    opacity: 0;
+  }
+}
diff --git a/src/main/resources/static/images/update.svg b/src/main/resources/static/images/update.svg
new file mode 100644
index 00000000..3edc4c67
--- /dev/null
+++ b/src/main/resources/static/images/update.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21,10.12H14.22L16.96,7.3C14.23,4.6 9.81,4.5 7.08,7.2C4.35,9.91 4.35,14.28 7.08,17C9.81,19.7 14.23,19.7 16.96,17C18.32,15.65 19,14.08 19,12.1H21C21,14.08 20.12,16.65 18.36,18.39C14.85,21.87 9.15,21.87 5.64,18.39C2.14,14.92 2.11,9.28 5.62,5.81C9.13,2.34 14.76,2.34 18.27,5.81L21,3V10.12M12.5,8V12.25L16,14.33L15.28,15.54L11,13V8H12.5Z" /></svg>
\ No newline at end of file
diff --git a/src/main/resources/static/js/githubVersion.js b/src/main/resources/static/js/githubVersion.js
index e17524d5..b312fd85 100644
--- a/src/main/resources/static/js/githubVersion.js
+++ b/src/main/resources/static/js/githubVersion.js
@@ -30,19 +30,39 @@ async function getLatestReleaseVersion() {
 
 async function checkForUpdate() {
   // Initialize the update button as hidden
-  var updateBtn = document.getElementById("update-btn");
+  var updateBtn = document.getElementById("update-btn") || null;
+  var updateLink = document.getElementById("update-link") || null;
   if (updateBtn !== null) {
     updateBtn.style.display = "none";
   }
+  if (updateLink !== null) {
+    console.log("hidden!");
+    if (!updateLink.classList.contains("visually-hidden")) {
+      updateLink.classList.add("visually-hidden");
+    }
+  }
 
   const latestVersion = await getLatestReleaseVersion();
   console.log("latestVersion=" + latestVersion);
   console.log("currentVersion=" + currentVersion);
   console.log("compareVersions(latestVersion, currentVersion) > 0)=" + compareVersions(latestVersion, currentVersion));
   if (latestVersion && compareVersions(latestVersion, currentVersion) > 0) {
-    document.getElementById("update-btn").style.display = "block";
+    if (updateBtn != null) {
+      document.getElementById("update-btn").style.display = "block";
+    }
+    if (updateLink !== null) {
+      document.getElementById("app-update").innerHTML = updateAvailable.replace("{0}", '<b>' + currentVersion + '</b>').replace("{1}", '<b>' + latestVersion + '</b>');
+      if (updateLink.classList.contains("visually-hidden")) {
+        updateLink.classList.remove("visually-hidden");
+      }
+    }
     console.log("visible");
   } else {
+    if (updateLink !== null) {
+      if (!updateLink.classList.contains("visually-hidden")) {
+        updateLink.classList.add("visually-hidden");
+      }
+    }
     console.log("hidden");
   }
 }
diff --git a/src/main/resources/static/js/homecard.js b/src/main/resources/static/js/homecard.js
index 8ac2ef44..c461af3c 100644
--- a/src/main/resources/static/js/homecard.js
+++ b/src/main/resources/static/js/homecard.js
@@ -46,6 +46,12 @@ function reorderCards() {
   cards.sort(function (a, b) {
     var aIsFavorite = localStorage.getItem(a.id) === "favorite";
     var bIsFavorite = localStorage.getItem(b.id) === "favorite";
+    if (a.id === "update-link") {
+      return -1;
+    }
+    if (b.id === "update-link") {
+      return 1;
+    }
     if (aIsFavorite && !bIsFavorite) {
       return -1;
     }
diff --git a/src/main/resources/templates/fragments/navbar.html b/src/main/resources/templates/fragments/navbar.html
index 09b833dd..414ff51f 100644
--- a/src/main/resources/templates/fragments/navbar.html
+++ b/src/main/resources/templates/fragments/navbar.html
@@ -3,6 +3,7 @@
           <script th:inline="javascript">
             const currentVersion = /*[[${@appVersion}]]*/ '';
             const noFavourites = /*[[#{noFavourites}]]*/ '';
+            const updateAvailable =  /*[[#{settings.updateAvailable}]]*/ '';
           </script>
           <script th:src="@{js/githubVersion.js}"></script>
           <nav class="navbar navbar-expand-lg navbar-light bg-light">
@@ -194,7 +195,7 @@
                     <p class="mb-0" th:utext="#{settings.appVersion} + ' ' + ${@appVersion}"></p>
                     <a href="https://github.com/sponsors/Frooodle" class="btn btn-sm btn-outline-primary" role="button" target="_blank" th:text="#{sponsor}+' Stirling-PDF'"></a>
                     <a href="swagger-ui/index.html" class="btn btn-sm btn-outline-primary" role="button" target="_blank">API</a>
-                    <a href="https://github.com/Stirling-Tools/Stirling-PDF/releases" class="btn btn-sm btn-outline-primary" id="update-btn" th:utext="#{settings.update}" role="button" target="_blank"></a>
+                    <a th:if="${@shouldShow}" href="https://github.com/Stirling-Tools/Stirling-PDF/releases" class="btn btn-sm btn-outline-primary" id="update-btn" th:utext="#{settings.update}" role="button" target="_blank" rel="noopener"></a>
                   </div>
                   <div class="mb-3">
                     <label for="downloadOption" th:utext="#{settings.downloadOption.title}"></label>
@@ -210,7 +211,7 @@
                     <span id="zipThresholdValue" class="ms-2"></span>
                   </div>
                   <div class="mb-3 form-check">
-                    <input type="checkbox" class="form-check-input" id="boredWaiting" th:title="#{settings.bored.help}">
+                    <input type="checkbox" class="form-check-input"id="boredWaiting" th:title="#{settings.bored.help}">
                     <label class="form-check-label" for="boredWaiting" th:text="#{bored}"></label>
                   </div>
                   <div class="mb-3 form-check">
diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/home.html
index ed1c6a18..83528d4f 100644
--- a/src/main/resources/templates/home.html
+++ b/src/main/resources/templates/home.html
@@ -23,6 +23,15 @@
           <br>
           <input type="text" id="searchBar" onkeyup="filterCards()" th:placeholder="#{home.searchBar}" autofocus>
           <div class="features-container">
+            <div th:if="${@shouldShow}" class="feature-card favorite" id="update-link" style="display: none;">
+              <a href="https://github.com/Stirling-Tools/Stirling-PDF/releases" target="_blank" class="nav-link text-body-secondary px-2" rel="noopener">
+                <div class="d-flex align-items-center">
+                  <img class="card-icon home-card-icon home-card-icon-colour" src="images/update.svg" alt="Icon" width="30" height="30">
+                  <h5 class="card-title lookatme ms-2" th:text="#{settings.update}" th:data-lookatme-text="#{settings.update}"></h5>
+                </div>
+                <p class="card-text" id="app-update"></p>
+              </a>
+            </div>
             <div th:replace="~{fragments/card :: card(id='pipeline', cardTitle=#{home.pipeline.title}, cardText=#{home.pipeline.desc}, cardLink='pipeline', svgPath='images/pipeline.svg', tags=#{pipeline.tags})}"></div>
 
             <div th:replace="~{fragments/card :: card(id='view-pdf', cardTitle=#{home.viewPdf.title}, cardText=#{home.viewPdf.desc}, cardLink='view-pdf', svgPath='images/book-opened.svg', tags=#{viewPdf.tags})}"></div>