diff options
author | Andrew Dolgov <[email protected]> | 2021-02-14 22:17:13 +0300 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2021-02-14 22:17:13 +0300 |
commit | a2e688fcb2d463a5db700ebd013c783e3a8f4971 (patch) | |
tree | 5ebd94a52899b00e75e4a5ab2fb61a26450123fa | |
parent | 37a81ba594c2b848b8ecec805527ee8766f1ed14 (diff) |
render headline-specific toolbar on the client
-rwxr-xr-x | classes/feeds.php | 123 | ||||
-rwxr-xr-x | classes/pref/feeds.php | 22 | ||||
-rw-r--r-- | index.php | 4 | ||||
-rw-r--r-- | js/CommonDialogs.js | 13 | ||||
-rwxr-xr-x | js/Headlines.js | 61 | ||||
-rw-r--r-- | plugins/mail/init.php | 7 | ||||
-rw-r--r-- | plugins/mailto/init.php | 5 | ||||
-rw-r--r-- | themes/compact.css | 5 | ||||
-rw-r--r-- | themes/compact_night.css | 5 | ||||
-rw-r--r-- | themes/light.css | 5 | ||||
-rw-r--r-- | themes/light/tt-rss.less | 4 | ||||
-rw-r--r-- | themes/night.css | 5 | ||||
-rw-r--r-- | themes/night_blue.css | 5 |
13 files changed, 136 insertions, 128 deletions
diff --git a/classes/feeds.php b/classes/feeds.php index e6bd1459d..0a3e77a1a 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -16,103 +16,6 @@ class Feeds extends Handler_Protected { return array_search($method, $csrf_ignored) !== false; } - private function format_headline_subtoolbar($feed_site_url, $feed_title, - $feed_id, $is_cat, $search, - $error, $feed_last_updated) { - - $cat_q = $is_cat ? "&is_cat=$is_cat" : ""; - - if ($search) { - $search_q = "&q=$search"; - } else { - $search_q = ""; - } - - $reply = ""; - - $rss_link = htmlspecialchars(get_self_url_prefix() . - "/public.php?op=rss&id=${feed_id}${cat_q}${search_q}"); - - $reply .= "<span class='left'>"; - - $reply .= "<a href=\"#\" - title=\"".__("Show as feed")."\" - onclick='CommonDialogs.generatedFeed(\"$feed_id\", \"$is_cat\", \"$rss_link\")'> - <i class='icon-syndicate material-icons'>rss_feed</i></a>"; - - $reply .= "<span id='feed_title'>"; - - if ($feed_site_url) { - $last_updated = T_sprintf("Last updated: %s", $feed_last_updated); - - $reply .= "<a title=\"$last_updated\" target='_blank' href=\"$feed_site_url\">". - truncate_string(strip_tags($feed_title), 30)."</a>"; - } else { - $reply .= strip_tags($feed_title); - } - - if ($error) - $reply .= " <i title=\"" . htmlspecialchars($error) . "\" class='material-icons icon-error'>error</i>"; - - $reply .= "</span>"; - $reply .= "<span id='feed_current_unread' style='display: none'></span>"; - $reply .= "</span>"; - - $reply .= "<span class=\"right\">"; - $reply .= "<span id='selected_prompt'></span>"; - $reply .= " "; - - $reply .= "<div dojoType='fox.form.DropDownButton' title='".__('Select articles')."'> - <span>".__("Select...")."</span> - <div dojoType='dijit.Menu' style='display: none;'> - <div dojoType='dijit.MenuItem' onclick='Headlines.select(\"all\")'>".__('All')."</div> - <div dojoType='dijit.MenuItem' onclick='Headlines.select(\"unread\")'>".__('Unread')."</div> - <div dojoType='dijit.MenuItem' onclick='Headlines.select(\"invert\")'>".__('Invert')."</div> - <div dojoType='dijit.MenuItem' onclick='Headlines.select(\"none\")'>".__('None')."</div> - <div dojoType='dijit.MenuSeparator'></div> - <div dojoType='dijit.MenuItem' onclick='Headlines.selectionToggleUnread()'>".__('Toggle unread')."</div> - <div dojoType='dijit.MenuItem' onclick='Headlines.selectionToggleMarked()'>".__('Toggle starred')."</div> - <div dojoType='dijit.MenuItem' onclick='Headlines.selectionTogglePublished()'>".__('Toggle published')."</div> - <div dojoType='dijit.MenuSeparator'></div> - <div dojoType='dijit.MenuItem' onclick='Headlines.catchupSelection()'>".__('Mark as read')."</div> - <div dojoType='dijit.MenuItem' onclick='Article.selectionSetScore()'>".__('Set score')."</div>"; - - // TODO: move to mail plugin - if (PluginHost::getInstance()->get_plugin("mail")) { - $reply .= "<div dojoType='dijit.MenuItem' value='Plugins.Mail.send()'>".__('Forward by email')."</div>"; - } - - // TODO: move to mailto plugin - if (PluginHost::getInstance()->get_plugin("mailto")) { - $reply .= "<div dojoType='dijit.MenuItem' value='Plugins.Mailto.send()'>".__('Forward by email')."</div>"; - } - - PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_HEADLINE_TOOLBAR_SELECT_MENU_ITEM, - function ($result) use (&$reply) { - $reply .= $result; - }, - $feed_id, $is_cat); - - if ($feed_id == 0 && !$is_cat) { - $reply .= "<div dojoType='dijit.MenuSeparator'></div> - <div dojoType='dijit.MenuItem' class='text-error' onclick='Headlines.deleteSelection()'>".__('Delete permanently')."</div>"; - } - - $reply .= "</div>"; /* menu */ - - $reply .= "</div>"; /* dropdown */ - - PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_HEADLINE_TOOLBAR_BUTTON, - function ($result) use (&$reply) { - $reply .= $result; - }, - $feed_id, $is_cat); - - $reply .= "</span>"; - - return $reply; - } - private function format_headlines_list($feed, $method, $view_mode, $limit, $cat_view, $offset, $override_order = false, $include_children = false, $check_first_id = false, $skip_first_id_check = false, $order_by = false) { @@ -222,10 +125,28 @@ class Feeds extends Handler_Protected { $reply['search_query'] = [$search, $search_language]; $reply['vfeed_group_enabled'] = $vfeed_group_enabled; - $reply['toolbar'] = $this->format_headline_subtoolbar($feed_site_url, - $feed_title, - $feed, $cat_view, $search, - $last_error, $last_updated); + $plugin_menu_items = ""; + PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_HEADLINE_TOOLBAR_SELECT_MENU_ITEM, + function ($result) use (&$plugin_menu_items) { + $plugin_menu_items .= $result; + }, + $feed, $cat_view); + + $plugin_buttons = ""; + PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_HEADLINE_TOOLBAR_BUTTON, + function ($result) use (&$plugin_buttons) { + $plugin_buttons .= $result; + }, + $feed, $cat_view); + + $reply['toolbar'] = [ + 'site_url' => $feed_site_url, + 'title' => truncate_string(strip_tags($feed_title), 30), + 'error' => $last_error, + 'last_updated' => $last_updated, + 'plugin_menu_items' => $plugin_menu_items, + 'plugin_buttons' => $plugin_buttons, + ]; $reply['content'] = []; diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php index 6b5df0289..e225949f2 100755 --- a/classes/pref/feeds.php +++ b/classes/pref/feeds.php @@ -1358,14 +1358,12 @@ class Pref_Feeds extends Handler_Protected { } private function index_shared() { - $rss_url = htmlspecialchars(get_self_url_prefix() . - "/public.php?op=rss&id=-2&view-mode=all_articles"); ?> <h3><?= __('Published articles can be subscribed by anyone who knows the following URL:') ?></h3> <button dojoType='dijit.form.Button' class='alt-primary' - onclick='CommonDialogs.generatedFeed(-2, false, "<?= $rss_url ?>", "<?= __("Published articles") ?>")'> + onclick="CommonDialogs.generatedFeed(-2, false)"> <?= __('Display URL') ?> </button> @@ -1603,11 +1601,23 @@ class Pref_Feeds extends Handler_Protected { print json_encode(["link" => $new_key]); } - function getFeedKey() { + function getsharedurl() { $feed_id = clean($_REQUEST['id']); - $is_cat = clean($_REQUEST['is_cat']); + $is_cat = clean($_REQUEST['is_cat']) == "true"; + $search = clean($_REQUEST['search']); + + $link = get_self_url_prefix() . "/public.php?" . http_build_query([ + 'op' => 'rss', + 'id' => $feed_id, + 'is_cat' => (int)$is_cat, + 'q' => $search, + 'key' => Feeds::get_feed_access_key($feed_id, $is_cat, $_SESSION["uid"]) + ]); - print json_encode(["link" => Feeds::get_feed_access_key($feed_id, $is_cat, $_SESSION["uid"])]); + print json_encode([ + "title" => Feeds::getFeedTitle($feed_id, $is_cat), + "link" => $link + ]); } private function update_feed_access_key($feed_id, $is_cat, $owner_uid) { @@ -176,9 +176,9 @@ }); ?> - <form id="toolbar-headlines" action="" style="order : 10" onsubmit='return false'> + <div id="toolbar-headlines" dojoType="fox.Toolbar" style="order : 10"> - </form> + </div> <form id="toolbar-main" action="" style="order : 20" onsubmit='return false'> diff --git a/js/CommonDialogs.js b/js/CommonDialogs.js index 5a72f705b..e6b1822c2 100644 --- a/js/CommonDialogs.js +++ b/js/CommonDialogs.js @@ -433,24 +433,19 @@ const CommonDialogs = { } }); }, - generatedFeed: function(feed, is_cat, rss_url, feed_title) { + generatedFeed: function(feed, is_cat, search = "") { Notify.progress("Loading, please wait...", true); - xhrJson("backend.php", {op: "pref-feeds", method: "getFeedKey", id: feed, is_cat: is_cat}, (reply) => { + xhrJson("backend.php", {op: "pref-feeds", method: "getsharedurl", id: feed, is_cat: is_cat, search: search}, (reply) => { try { - if (!feed_title && typeof Feeds != "undefined") - feed_title = Feeds.getName(feed, is_cat); - - const secret_url = rss_url + "&key=" + encodeURIComponent(reply.link); - const dialog = new fox.SingleUseDialog({ title: __("Show as feed"), content: ` - <header>${__("%s can be accessed via the following secret URL:").replace("%s", feed_title)}</header> + <header>${__("%s can be accessed via the following secret URL:").replace("%s", App.escapeHtml(reply.title))}</header> <section> <div class='panel text-center'> - <a id='gen_feed_url' href="${App.escapeHtml(secret_url)}" target='_blank'>${secret_url}</a> + <a id='gen_feed_url' href="${App.escapeHtml(reply.link)}" target='_blank'>${App.escapeHtml(reply.link)}</a> </div> </section> <footer> diff --git a/js/Headlines.js b/js/Headlines.js index ea4c81a6a..954b6b45f 100755 --- a/js/Headlines.js +++ b/js/Headlines.js @@ -566,6 +566,58 @@ const Headlines = { } } }, + renderToolbar: function(headlines) { + + const tb = headlines['toolbar']; + const search_query = Feeds._search_query ? Feeds._search_query.query : ""; + const target = dijit.byId('toolbar-headlines'); + + target.attr('innerHTML', + ` + <span class='left'> + <a href="#" title="${__("Show as feed")}" + onclick='CommonDialogs.generatedFeed("${headlines.id}", ${headlines.is_cat}, "${App.escapeHtml(search_query)}")'> + <i class='icon-syndicate material-icons'>rss_feed</i> + </a> + ${tb.site_url ? + `<a class="feed_title" target="_blank" href="${App.escapeHtml(tb.site_url)}" title="${tb.last_updated}">${tb.title}</a>` : + `<span class="feed_title">${tb.title}</span>`} + ${search_query ? + ` + <span class='cancel_search'>(<a href='#' onclick='Feeds.cancelSearch()'>${__("Cancel search")}</a>)</span> + ` : ''} + ${tb.error ? `<i title="${App.escapeHtml(tb.error)}" class='material-icons icon-error'>error</i>` : ''} + <span id='feed_current_unread' style='display: none'></span> + </span> + <span class='right'> + <span id='selected_prompt'></span> + <div dojoType='fox.form.DropDownButton' title='"${__('Select articles')}'> + <span>${__("Select...")}</span> + <div dojoType='dijit.Menu' style='display: none;'> + <div dojoType='dijit.MenuItem' onclick='Headlines.select("all")'>${__('All')}</div> + <div dojoType='dijit.MenuItem' onclick='Headlines.select("unread")'>${__('Unread')}</div> + <div dojoType='dijit.MenuItem' onclick='Headlines.select("invert")'>${__('Invert')}</div> + <div dojoType='dijit.MenuItem' onclick='Headlines.select("none")'>${__('None')}</div> + <div dojoType='dijit.MenuSeparator'></div> + <div dojoType='dijit.MenuItem' onclick='Headlines.selectionToggleUnread()'>${__('Toggle unread')}</div> + <div dojoType='dijit.MenuItem' onclick='Headlines.selectionToggleMarked()'>${__('Toggle starred')}</div> + <div dojoType='dijit.MenuItem' onclick='Headlines.selectionTogglePublished()'>${__('Toggle published')}</div> + <div dojoType='dijit.MenuSeparator'></div> + <div dojoType='dijit.MenuItem' onclick='Headlines.catchupSelection()'>${__('Mark as read')}</div> + <div dojoType='dijit.MenuItem' onclick='Article.selectionSetScore()'>${__('Set score')}</div> + ${tb.plugin_menu_items} + ${headlines.id === 0 && !headlines.is_cat ? + ` + <div dojoType='dijit.MenuSeparator'></div> + <div dojoType='dijit.MenuItem' class='text-error' onclick='Headlines.deleteSelection()'>${__('Delete permanently')}</div> + ` : ''} + </div> + ${tb.plugin_buttons} + </span> + `); + + dojo.parser.parse(target.domNode); + }, onLoaded: function (transport, offset, append) { const reply = App.handleRpcJson(transport); @@ -613,9 +665,11 @@ const Headlines = { this.headlines = []; this.vgroup_last_feed = undefined; - dojo.html.set($("toolbar-headlines"), + /*dojo.html.set($("toolbar-headlines"), reply['headlines']['toolbar'], - {parseContent: true}); + {parseContent: true});*/ + + Headlines.renderToolbar(reply['headlines']); if (typeof reply['headlines']['content'] == 'string') { $("headlines-frame").innerHTML = reply['headlines']['content']; @@ -646,11 +700,12 @@ const Headlines = { hsp.innerHTML = "<a href='#' onclick='Feeds.openNextUnread()'>" + __("Click to open next unread feed.") + "</a>"; + /* if (Feeds._search_query) { $("feed_title").innerHTML += "<span id='cancel_search'>" + " (<a href='#' onclick='Feeds.cancelSearch()'>" + __("Cancel search") + "</a>)" + "</span>"; - } + } */ Headlines.updateCurrentUnread(); diff --git a/plugins/mail/init.php b/plugins/mail/init.php index 40d147fc9..829620ebc 100644 --- a/plugins/mail/init.php +++ b/plugins/mail/init.php @@ -15,12 +15,17 @@ class Mail extends Plugin { $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this); $host->add_hook($host::HOOK_PREFS_TAB, $this); + $host->add_hook($host::HOOK_HEADLINE_TOOLBAR_SELECT_MENU_ITEM, $this); } function get_js() { return file_get_contents(dirname(__FILE__) . "/mail.js"); } + function hook_headline_toolbar_select_menu_item($feed_id, $is_cat) { + return "<div dojoType='dijit.MenuItem' onclick='Plugins.Mail.send()'>".__('Forward by email')."</div>"; + } + function save() { $addresslist = $_POST["addresslist"]; @@ -32,7 +37,7 @@ class Mail extends Plugin { function hook_prefs_tab($args) { if ($args != "prefPrefs") return; - print "<div dojoType=\"dijit.layout.AccordionPane\" + print "<div dojoType=\"dijit.layout.AccordionPane\" title=\"<i class='material-icons'>mail</i> ".__('Mail plugin')."\">"; print "<p>" . __("You can set predefined email addressed here (comma-separated list):") . "</p>"; diff --git a/plugins/mailto/init.php b/plugins/mailto/init.php index 390984b71..3e24dcf29 100644 --- a/plugins/mailto/init.php +++ b/plugins/mailto/init.php @@ -12,6 +12,11 @@ class MailTo extends Plugin { $this->host = $host; $host->add_hook($host::HOOK_ARTICLE_BUTTON, $this); + $host->add_hook($host::HOOK_HEADLINE_TOOLBAR_SELECT_MENU_ITEM, $this); + } + + function hook_headline_toolbar_select_menu_item($feed_id, $is_cat) { + return "<div dojoType='dijit.MenuItem' onclick='Plugins.Mailto.send()'>".__('Forward by email')."</div>"; } function get_js() { diff --git a/themes/compact.css b/themes/compact.css index 24380d428..6e4f59c84 100644 --- a/themes/compact.css +++ b/themes/compact.css @@ -704,6 +704,8 @@ body.ttrss_main #toolbar-frame #toolbar i { margin: 0 4px; } body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines { + font-size: 12px; + background: transparent; padding-right: 4px; flex-grow: 2; display: flex; @@ -713,7 +715,8 @@ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left { display: flex; align-items: center; } -body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left #feed_title { +body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title, +body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .cancel_search { margin-left: 4px; } body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .right { diff --git a/themes/compact_night.css b/themes/compact_night.css index a366404a4..7dd4c0b0e 100644 --- a/themes/compact_night.css +++ b/themes/compact_night.css @@ -704,6 +704,8 @@ body.ttrss_main #toolbar-frame #toolbar i { margin: 0 4px; } body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines { + font-size: 12px; + background: transparent; padding-right: 4px; flex-grow: 2; display: flex; @@ -713,7 +715,8 @@ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left { display: flex; align-items: center; } -body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left #feed_title { +body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title, +body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .cancel_search { margin-left: 4px; } body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .right { diff --git a/themes/light.css b/themes/light.css index d3f5d7978..6f70862d6 100644 --- a/themes/light.css +++ b/themes/light.css @@ -704,6 +704,8 @@ body.ttrss_main #toolbar-frame #toolbar i { margin: 0 4px; } body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines { + font-size: 12px; + background: transparent; padding-right: 4px; flex-grow: 2; display: flex; @@ -713,7 +715,8 @@ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left { display: flex; align-items: center; } -body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left #feed_title { +body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title, +body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .cancel_search { margin-left: 4px; } body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .right { diff --git a/themes/light/tt-rss.less b/themes/light/tt-rss.less index d13ffff3e..4632997ba 100644 --- a/themes/light/tt-rss.less +++ b/themes/light/tt-rss.less @@ -820,6 +820,8 @@ body.ttrss_main { } #toolbar-headlines { + font-size : 12px; + background: transparent; padding-right : 4px; flex-grow : 2; display : flex; @@ -829,7 +831,7 @@ body.ttrss_main { display : flex; align-items : center; - #feed_title { + .feed_title, .cancel_search { margin-left : 4px; } } diff --git a/themes/night.css b/themes/night.css index 87a68a3c0..579f6dcdf 100644 --- a/themes/night.css +++ b/themes/night.css @@ -705,6 +705,8 @@ body.ttrss_main #toolbar-frame #toolbar i { margin: 0 4px; } body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines { + font-size: 12px; + background: transparent; padding-right: 4px; flex-grow: 2; display: flex; @@ -714,7 +716,8 @@ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left { display: flex; align-items: center; } -body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left #feed_title { +body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title, +body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .cancel_search { margin-left: 4px; } body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .right { diff --git a/themes/night_blue.css b/themes/night_blue.css index 02a66656b..3697cff05 100644 --- a/themes/night_blue.css +++ b/themes/night_blue.css @@ -705,6 +705,8 @@ body.ttrss_main #toolbar-frame #toolbar i { margin: 0 4px; } body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines { + font-size: 12px; + background: transparent; padding-right: 4px; flex-grow: 2; display: flex; @@ -714,7 +716,8 @@ body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left { display: flex; align-items: center; } -body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left #feed_title { +body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .feed_title, +body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .left .cancel_search { margin-left: 4px; } body.ttrss_main #toolbar-frame #toolbar #toolbar-headlines .right { |