diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php index 854b70549..7e83a6e64 100644 --- a/classes/pref/prefs.php +++ b/classes/pref/prefs.php @@ -787,164 +787,73 @@ class Pref_Prefs extends Handler_Protected { config.php for all users."); - - $system_enabled = array_map("trim", explode(",", (string)Config::get(Config::PLUGINS))); - - $tmppluginhost = new PluginHost(); - $tmppluginhost->load_all($tmppluginhost::KIND_ALL, $_SESSION["uid"], true); - - foreach ($tmppluginhost->get_plugins() as $name => $plugin) { - $about = $plugin->about(); - $is_local = $tmppluginhost->is_local($plugin); - $version = htmlspecialchars($this->_get_plugin_version($plugin)); - - if ($about[3] ?? false) { - $is_checked = in_array($name, $system_enabled) ? "checked" : ""; - ?> -
- - - - get_all($plugin)) > 0) { - if (in_array($name, $system_enabled)) { ?> - - - - - - - - = 10) { ?> - - - - = 10 && $is_local) { ?> - - - - -
- -
- -
- load_all($tmppluginhost::KIND_ALL, $_SESSION["uid"], true); + $rv = []; + foreach ($tmppluginhost->get_plugins() as $name => $plugin) { $about = $plugin->about(); $is_local = $tmppluginhost->is_local($plugin); $version = htmlspecialchars($this->_get_plugin_version($plugin)); - if (empty($about[3]) || $about[3] == false) { - - $is_checked = ""; - $is_disabled = ""; - - if (in_array($name, $system_enabled)) { - $is_checked = "checked='1'"; - $is_disabled = "disabled='1'"; - } else if (in_array($name, $user_enabled)) { - $is_checked = "checked='1'"; - } - ?> - -
- - - - get_all($plugin)) > 0) { - if (in_array($name, $system_enabled) || in_array($name, $user_enabled)) { ?> - - - - - - - - = 10) { ?> - - - - = 10 && $is_local) { ?> - - - - -
- -
- - -
- $name, + "is_local" => $is_local, + "system_enabled" => in_array($name, $system_enabled), + "user_enabled" => in_array($name, $user_enabled), + "has_data" => count($tmppluginhost->get_all($plugin)) > 0, + "is_system" => (bool)($about[3] ?? false), + "version" => $version, + "author" => $about[2] ?? "", + "description" => $about[1] ?? "", + "more_info" => $about[4] ?? "", + ]); } + + usort($rv, function($a, $b) { return strcmp($a["name"], $b["name"]); }); + + print json_encode(['plugins' => $rv, 'is_admin' => $_SESSION['access_level'] >= 10]); } function index_plugins() { ?>
-
+
+
+ + +
+ +
+ +
+
+
+
+
+
+
- + Helpers.Plugins.reload(); + + + -

- - index_plugins_system() ?> - -

- - index_plugins_user() ?> +
    +
  • +
- - + "alt-primary", + "onclick" => "Helpers.Plugins.enableSelected()"]) ?> + + __("Reload"), "onclick" => "Helpers.Plugins.reload()"]) ?> + = 10) { ?> - - - @@ -1031,16 +933,8 @@ class Pref_Prefs extends Handler_Protected {
index_prefs() ?>
-
- - +
+ index_plugins() ?>
run_hooks(PluginHost::HOOK_PREFS_TAB, "prefPrefs") ?>
@@ -1119,12 +1013,9 @@ class Pref_Prefs extends Handler_Protected { } function setplugins() { - if (is_array(clean($_REQUEST["plugins"]))) - $plugins = join(",", clean($_REQUEST["plugins"])); - else - $plugins = ""; + $plugins = array_filter($_REQUEST["plugins"], 'clean') ?? []; - set_pref(Prefs::_ENABLED_PLUGINS, $plugins); + set_pref(Prefs::_ENABLED_PLUGINS, implode(",", $plugins)); } function _get_plugin_version(Plugin $plugin) { diff --git a/js/PrefHelpers.js b/js/PrefHelpers.js index b72dbc881..296028f44 100644 --- a/js/PrefHelpers.js +++ b/js/PrefHelpers.js @@ -308,8 +308,95 @@ const Helpers = { }, }, Plugins: { - clearPluginData: function(name) { - if (confirm(__("Clear stored data for this plugin?"))) { + _list_of_plugins: [], + _search_query: "", + enableSelected: function() { + const form = dijit.byId("changePluginsForm"); + + if (form.validate()) { + xhr.post("backend.php", form.getValues(), () => { + Notify.close(); + if (confirm(__('Selected plugins have been enabled. Reload?'))) { + window.location.reload(); + } + }) + } + }, + search: function() { + this._search_query = dijit.byId("changePluginsForm").getValues().search; + this.render_contents(); + }, + reload: function() { + xhr.json("backend.php", {op: "pref-prefs", method: "getPluginsList"}, (reply) => { + this._list_of_plugins = reply; + this.render_contents(); + }); + }, + render_contents: function() { + const container = document.querySelector(".prefs-plugin-list"); + + container.innerHTML = ""; + let results_rendered = 0; + + const is_admin = this._list_of_plugins.is_admin; + + const search_tokens = this._search_query + .split(/ {1,}/) + .filter((stoken) => (stoken.length > 0 ? stoken : null)); + + this._list_of_plugins.plugins.forEach((plugin) => { + + if (search_tokens.length == 0 || + Object.values(plugin).filter((pval) => + search_tokens.filter((stoken) => + (pval.toString().indexOf(stoken) != -1 ? stoken : null) + ).length == search_tokens.length).length > 0) { + + ++results_rendered; + + container.innerHTML += ` +
  • +
  • + ${plugin.name}: + +
    + ${plugin.description} +
    +
    + ${plugin.is_system ? + App.FormFields.button_tag(App.FormFields.icon("security"), "", + {disabled: true}) : ''} + ${plugin.more_info ? + App.FormFields.button_tag(App.FormFields.icon("help"), "", + {class: 'alt-info', onclick: `window.open("${App.escapeHtml(plugin.more_info)}")`}) : ''} + ${is_admin && plugin.is_local ? + App.FormFields.button_tag(App.FormFields.icon("update"), "", + {title: __("Update"), class: 'alt-warning', "data-update-btn-for-plugin": plugin.name, style: 'display : none', + onclick: `Helpers.Plugins.update("${App.escapeHtml(plugin.name)}")`}) : ''} + ${is_admin && plugin.has_data ? + App.FormFields.button_tag(App.FormFields.icon("clear"), "", + {title: __("Clear data"), onclick: `Helpers.Plugins.clearData("${App.escapeHtml(plugin.name)}")`}) : ''} + ${is_admin && plugin.is_local ? + App.FormFields.button_tag(App.FormFields.icon("delete"), "", + {title: __("Uninstall"), onclick: `Helpers.Plugins.uninstall("${App.escapeHtml(plugin.name)}")`}) : ''} +
    +
    ${plugin.version}
    + + `; + } + }); + + if (results_rendered == 0) { + container.innerHTML = `
  • ${__("Could not find any plugins for this search query.")}
  • `; + } + + dojo.parser.parse(container); + + }, + clearData: function(name) { + if (confirm(__("Clear stored data for %s?").replace("%s", name))) { Notify.progress("Loading, please wait..."); xhr.post("backend.php", {op: "pref-prefs", method: "clearPluginData", name: name}, () => { @@ -317,36 +404,6 @@ const Helpers = { }); } }, - checkForUpdate: function(name = null) { - Notify.progress("Checking for plugin updates..."); - - xhr.json("backend.php", {op: "pref-prefs", method: "checkForPluginUpdates", name: name}, (reply) => { - Notify.close(); - - if (reply) { - let plugins_with_updates = 0; - - reply.forEach((p) => { - if (p.rv.o) { - const button = dijit.getEnclosingWidget(App.find(`*[data-update-btn-for-plugin="${p.plugin}"]`)); - - if (button) { - button.domNode.show(); - ++plugins_with_updates; - } - } - }); - - if (plugins_with_updates > 0) - App.find(".update-all-plugins-btn").show(); - else - Notify.info("All local plugins are up-to-date."); - - } else { - Notify.error("Unable to check for plugin updates."); - } - }); - }, uninstall: function(plugin) { const msg = __("Uninstall plugin %s?").replace("%s", plugin); @@ -436,7 +493,13 @@ const Helpers = { }, search: function() { this.search_query = this.attr('value').search.toLowerCase(); - this.render_contents(); + + if ('requestIdleCallback' in window) + window.requestIdleCallback(() => { + this.render_contents(); + }); + else + this.render_contents(); }, render_contents: function() { const container = dialog.domNode.querySelector(".contents"); @@ -610,6 +673,12 @@ const Helpers = { dialog.plugins_to_update.push(p.plugin); } + const update_button = dijit.getEnclosingWidget( + App.find(`*[data-update-btn-for-plugin="${p.plugin}"]`)); + + if (update_button) + update_button.domNode.show(); + container.innerHTML += `
  • ${p.plugin}

    @@ -622,6 +691,11 @@ const Helpers = {
  • ` }); + + if (!enable_update_btn) { + container.innerHTML = `
  • ${name ? __("Plugin %s is up-to-date").replace("%s", name) : + __("All local plugins are up-to-date.")}
  • `; + } } dijit.getEnclosingWidget(dialog.domNode.querySelector(".update-btn")).attr('disabled', !enable_update_btn); diff --git a/themes/compact.css b/themes/compact.css index 227dea20f..6e17cf897 100644 --- a/themes/compact.css +++ b/themes/compact.css @@ -1514,6 +1514,43 @@ body.ttrss_prefs fieldset.plugin label.description .dijitCheckBox { body.ttrss_prefs .users-list td { cursor: pointer; } +body.ttrss_prefs ul.prefs-plugin-list { + margin: 0; + padding: 0; +} +body.ttrss_prefs ul.prefs-plugin-list li { + display: flex; + align-items: center; + line-height: 30px; + border-bottom: #ddd 1px solid; +} +body.ttrss_prefs ul.prefs-plugin-list li > * { + padding: 4px; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox { + display: flex; + align-items: center; + min-width: 200px; + margin-right: 16px; + cursor: pointer; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox.system { + cursor: auto; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name { + flex-grow: 2; + display: inline-block; + text-align: right; + font-weight: bold; +} +body.ttrss_prefs ul.prefs-plugin-list li .actions { + flex-grow: 2; + text-align: right; +} +body.ttrss_prefs ul.prefs-plugin-list li .version { + min-width: 200px; + text-align: right; +} body.ttrss_prefs .plugin-installer-list .plugin-installed { opacity: 0.5; } diff --git a/themes/compact_night.css b/themes/compact_night.css index 9830f2563..23dd2bcda 100644 --- a/themes/compact_night.css +++ b/themes/compact_night.css @@ -1514,6 +1514,43 @@ body.ttrss_prefs fieldset.plugin label.description .dijitCheckBox { body.ttrss_prefs .users-list td { cursor: pointer; } +body.ttrss_prefs ul.prefs-plugin-list { + margin: 0; + padding: 0; +} +body.ttrss_prefs ul.prefs-plugin-list li { + display: flex; + align-items: center; + line-height: 30px; + border-bottom: #222 1px solid; +} +body.ttrss_prefs ul.prefs-plugin-list li > * { + padding: 4px; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox { + display: flex; + align-items: center; + min-width: 200px; + margin-right: 16px; + cursor: pointer; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox.system { + cursor: auto; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name { + flex-grow: 2; + display: inline-block; + text-align: right; + font-weight: bold; +} +body.ttrss_prefs ul.prefs-plugin-list li .actions { + flex-grow: 2; + text-align: right; +} +body.ttrss_prefs ul.prefs-plugin-list li .version { + min-width: 200px; + text-align: right; +} body.ttrss_prefs .plugin-installer-list .plugin-installed { opacity: 0.5; } diff --git a/themes/light.css b/themes/light.css index 0640ebfdd..6fd026857 100644 --- a/themes/light.css +++ b/themes/light.css @@ -1514,6 +1514,43 @@ body.ttrss_prefs fieldset.plugin label.description .dijitCheckBox { body.ttrss_prefs .users-list td { cursor: pointer; } +body.ttrss_prefs ul.prefs-plugin-list { + margin: 0; + padding: 0; +} +body.ttrss_prefs ul.prefs-plugin-list li { + display: flex; + align-items: center; + line-height: 30px; + border-bottom: #ddd 1px solid; +} +body.ttrss_prefs ul.prefs-plugin-list li > * { + padding: 4px; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox { + display: flex; + align-items: center; + min-width: 200px; + margin-right: 16px; + cursor: pointer; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox.system { + cursor: auto; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name { + flex-grow: 2; + display: inline-block; + text-align: right; + font-weight: bold; +} +body.ttrss_prefs ul.prefs-plugin-list li .actions { + flex-grow: 2; + text-align: right; +} +body.ttrss_prefs ul.prefs-plugin-list li .version { + min-width: 200px; + text-align: right; +} body.ttrss_prefs .plugin-installer-list .plugin-installed { opacity: 0.5; } diff --git a/themes/light/prefs.less b/themes/light/prefs.less index 35db886ce..4ffcc5ab1 100644 --- a/themes/light/prefs.less +++ b/themes/light/prefs.less @@ -112,6 +112,51 @@ body.ttrss_prefs { } } + ul.prefs-plugin-list { + margin : 0; + padding : 0; + + li { + display : flex; + align-items : center; + line-height : 30px; + border-bottom: @border-default 1px solid; + + > * { + padding : 4px; + } + + label.checkbox { + display : flex; + align-items : center; + min-width : 200px; + margin-right : 16px; + cursor : pointer; + + &.system { + cursor : auto; + } + + .name { + flex-grow: 2; + display: inline-block; + text-align: right; + font-weight : bold; + } + } + + .actions { + flex-grow : 2; + text-align: right; + } + + .version { + min-width: 200px; + text-align: right; + } + } + } + .plugin-installer-list { .plugin-installed { opacity : 0.5; diff --git a/themes/night.css b/themes/night.css index a1b65608f..a0d69b88b 100644 --- a/themes/night.css +++ b/themes/night.css @@ -1515,6 +1515,43 @@ body.ttrss_prefs fieldset.plugin label.description .dijitCheckBox { body.ttrss_prefs .users-list td { cursor: pointer; } +body.ttrss_prefs ul.prefs-plugin-list { + margin: 0; + padding: 0; +} +body.ttrss_prefs ul.prefs-plugin-list li { + display: flex; + align-items: center; + line-height: 30px; + border-bottom: #222 1px solid; +} +body.ttrss_prefs ul.prefs-plugin-list li > * { + padding: 4px; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox { + display: flex; + align-items: center; + min-width: 200px; + margin-right: 16px; + cursor: pointer; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox.system { + cursor: auto; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name { + flex-grow: 2; + display: inline-block; + text-align: right; + font-weight: bold; +} +body.ttrss_prefs ul.prefs-plugin-list li .actions { + flex-grow: 2; + text-align: right; +} +body.ttrss_prefs ul.prefs-plugin-list li .version { + min-width: 200px; + text-align: right; +} body.ttrss_prefs .plugin-installer-list .plugin-installed { opacity: 0.5; } diff --git a/themes/night_blue.css b/themes/night_blue.css index cda01a990..9c8f7d848 100644 --- a/themes/night_blue.css +++ b/themes/night_blue.css @@ -1515,6 +1515,43 @@ body.ttrss_prefs fieldset.plugin label.description .dijitCheckBox { body.ttrss_prefs .users-list td { cursor: pointer; } +body.ttrss_prefs ul.prefs-plugin-list { + margin: 0; + padding: 0; +} +body.ttrss_prefs ul.prefs-plugin-list li { + display: flex; + align-items: center; + line-height: 30px; + border-bottom: #222 1px solid; +} +body.ttrss_prefs ul.prefs-plugin-list li > * { + padding: 4px; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox { + display: flex; + align-items: center; + min-width: 200px; + margin-right: 16px; + cursor: pointer; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox.system { + cursor: auto; +} +body.ttrss_prefs ul.prefs-plugin-list li label.checkbox .name { + flex-grow: 2; + display: inline-block; + text-align: right; + font-weight: bold; +} +body.ttrss_prefs ul.prefs-plugin-list li .actions { + flex-grow: 2; + text-align: right; +} +body.ttrss_prefs ul.prefs-plugin-list li .version { + min-width: 200px; + text-align: right; +} body.ttrss_prefs .plugin-installer-list .plugin-installed { opacity: 0.5; }