diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php
index d5a6dde76..8746aa1e0 100644
--- a/classes/pref/prefs.php
+++ b/classes/pref/prefs.php
@@ -1093,7 +1093,28 @@ class Pref_Prefs extends Handler_Protected {
set_pref(Prefs::_ENABLED_PLUGINS, $plugins);
}
- private function _plugin_needs_update($root_dir, $plugin_name) {
+ static function _get_updated_plugins() {
+ $root_dir = dirname(dirname(__DIR__)); # we're in classes/pref/
+ $plugin_dirs = array_filter(glob("$root_dir/plugins.local/*"), "is_dir");
+
+ $rv = [];
+
+ foreach ($plugin_dirs as $dir) {
+ if (is_dir("$dir/.git")) {
+ $plugin_name = basename($dir);
+
+ array_push($rv, ["plugin" => $plugin_name, "rv" => self::_plugin_needs_update($root_dir, $plugin_name)]);
+ }
+ }
+
+ $rv = array_values(array_filter($rv, function ($item) {
+ return !empty($item["rv"]["o"]);
+ }));
+
+ return $rv;
+ }
+
+ private static function _plugin_needs_update($root_dir, $plugin_name) {
$plugin_dir = "$root_dir/plugins.local/" . basename($plugin_name);
$rv = [];
@@ -1150,23 +1171,12 @@ class Pref_Prefs extends Handler_Protected {
if ($_SESSION["access_level"] >= 10) {
$plugin_name = $_REQUEST["name"] ?? "";
- # we're in classes/pref/
- $root_dir = dirname(dirname(__DIR__));
-
- $rv = [];
+ $root_dir = dirname(dirname(__DIR__)); # we're in classes/pref/
if (!empty($plugin_name)) {
- array_push($rv, ["plugin" => $plugin_name, "rv" => $this->_plugin_needs_update($root_dir, $plugin_name)]);
+ $rv = ["plugin" => $plugin_name, "rv" => self::_plugin_needs_update($root_dir, $plugin_name)];
} else {
- $plugin_dirs = array_filter(glob("$root_dir/plugins.local/*"), "is_dir");
-
- foreach ($plugin_dirs as $dir) {
- if (is_dir("$dir/.git")) {
- $plugin_name = basename($dir);
-
- array_push($rv, ["plugin" => $plugin_name, "rv" => $this->_plugin_needs_update($root_dir, $plugin_name)]);
- }
- }
+ $rv = self::_get_updated_plugins();
}
print json_encode($rv);
@@ -1191,7 +1201,7 @@ class Pref_Prefs extends Handler_Protected {
if (is_dir("$dir/.git")) {
$plugin_name = basename($dir);
- $test = $this->_plugin_needs_update($root_dir, $plugin_name);
+ $test = self::_plugin_needs_update($root_dir, $plugin_name);
if (!empty($test["o"]))
array_push($rv, ["plugin" => $plugin_name, "rv" => $this->_update_plugin($root_dir, $plugin_name)]);
diff --git a/classes/rpc.php b/classes/rpc.php
index 72e00a8bc..7f7b924eb 100755
--- a/classes/rpc.php
+++ b/classes/rpc.php
@@ -394,7 +394,7 @@ class RPC extends Handler_Protected {
}
function checkforupdates() {
- $rv = [];
+ $rv = ["changeset" => [], "plugins" => []];
$git_timestamp = false;
$git_commit = false;
@@ -411,10 +411,12 @@ class RPC extends Handler_Protected {
if ($git_timestamp < (int)$content["changeset"]["timestamp"] &&
$git_commit != $content["changeset"]["id"]) {
- $rv = $content["changeset"];
+ $rv["changeset"] = $content["changeset"];
}
}
}
+
+ $rv["plugins"] = Pref_Prefs::_get_updated_plugins();
}
print json_encode($rv);
diff --git a/js/App.js b/js/App.js
index 046365ff8..8eda5ac9d 100644
--- a/js/App.js
+++ b/js/App.js
@@ -812,10 +812,23 @@ const App = {
.then((reply) => {
console.log('update reply', reply);
- if (reply.id) {
- App.byId("updates-available").show();
+ const icon = App.byId("updates-available");
+
+ if (reply.changeset.id || reply.plugins.length > 0) {
+ icon.show();
+
+ const tips = [];
+
+ if (reply.changeset.id)
+ tips.push(__("Updates for Tiny Tiny RSS are available."));
+
+ if (reply.plugins.length > 0)
+ tips.push(__("Updates for some local plugins are available."));
+
+ icon.setAttribute("title", tips.join("\n"));
+
} else {
- App.byId("updates-available").hide();
+ icon.hide();
}
});
},
diff --git a/prefs.php b/prefs.php
index a6cbfd886..5762375a5 100644
--- a/prefs.php
+++ b/prefs.php
@@ -117,6 +117,7 @@
title="= __("Communication problem with server.") ?>">error_outline
">warning
+ new_releases
= __('Exit preferences') ?>
diff --git a/themes/compact.css b/themes/compact.css
index 16058309f..b5b421f19 100644
--- a/themes/compact.css
+++ b/themes/compact.css
@@ -763,6 +763,10 @@ body.ttrss_main #header i.log-alert {
color: #ddba1c;
cursor: pointer;
}
+body.ttrss_main #header #updates-available {
+ color: #69C671;
+ padding-right: 4px;
+}
body.ttrss_main #header i {
margin: 0 4px;
}
diff --git a/themes/compact_night.css b/themes/compact_night.css
index f1894f4de..0271b5310 100644
--- a/themes/compact_night.css
+++ b/themes/compact_night.css
@@ -763,6 +763,10 @@ body.ttrss_main #header i.log-alert {
color: #ddba1c;
cursor: pointer;
}
+body.ttrss_main #header #updates-available {
+ color: #69C671;
+ padding-right: 4px;
+}
body.ttrss_main #header i {
margin: 0 4px;
}
diff --git a/themes/light.css b/themes/light.css
index c014858ef..d88b0cfbe 100644
--- a/themes/light.css
+++ b/themes/light.css
@@ -763,6 +763,10 @@ body.ttrss_main #header i.log-alert {
color: #ddba1c;
cursor: pointer;
}
+body.ttrss_main #header #updates-available {
+ color: #69C671;
+ padding-right: 4px;
+}
body.ttrss_main #header i {
margin: 0 4px;
}
diff --git a/themes/light/tt-rss.less b/themes/light/tt-rss.less
index 35eec3e48..a4cf2f098 100644
--- a/themes/light/tt-rss.less
+++ b/themes/light/tt-rss.less
@@ -888,6 +888,11 @@ body.ttrss_main {
cursor : pointer;
}
+ #updates-available {
+ color : @color-checked;
+ padding-right : 4px;
+ }
+
i {
margin : 0 4px;
}
diff --git a/themes/night.css b/themes/night.css
index 1e397ee74..61f1d756a 100644
--- a/themes/night.css
+++ b/themes/night.css
@@ -764,6 +764,10 @@ body.ttrss_main #header i.log-alert {
color: #ddba1c;
cursor: pointer;
}
+body.ttrss_main #header #updates-available {
+ color: #69C671;
+ padding-right: 4px;
+}
body.ttrss_main #header i {
margin: 0 4px;
}
diff --git a/themes/night_blue.css b/themes/night_blue.css
index 361cd4fbf..39a4d4400 100644
--- a/themes/night_blue.css
+++ b/themes/night_blue.css
@@ -764,6 +764,10 @@ body.ttrss_main #header i.log-alert {
color: #ddba1c;
cursor: pointer;
}
+body.ttrss_main #header #updates-available {
+ color: #69C671;
+ padding-right: 4px;
+}
body.ttrss_main #header i {
margin: 0 4px;
}