From 82adb01307e108e8a2b4eeb900552160d730d0b7 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 15 Feb 2021 14:10:46 +0300 Subject: render enclosures on the client --- classes/api.php | 6 +- classes/article.php | 173 ++++++++++----------------------------- classes/feeds.php | 6 +- classes/handler/public.php | 13 ++- classes/rpc.php | 2 - include/controls.php | 31 ------- js/App.js | 18 ++-- js/Article.js | 58 ++++++++++++- js/Headlines.js | 2 +- plugins/shorten_expanded/init.js | 27 +++--- 10 files changed, 136 insertions(+), 200 deletions(-) diff --git a/classes/api.php b/classes/api.php index 6debad2f7..2531f0017 100755 --- a/classes/api.php +++ b/classes/api.php @@ -311,8 +311,6 @@ class API extends Handler { while ($line = $sth->fetch()) { - $attachments = Article::get_article_enclosures($line['id']); - $article = array( "id" => $line["id"], "guid" => $line["guid"], @@ -326,7 +324,7 @@ class API extends Handler { "author" => $line["author"], "updated" => (int) strtotime($line["updated"]), "feed_id" => $line["feed_id"], - "attachments" => $attachments, + "attachments" => Article::get_enclosures($line['id']), "score" => (int)$line["score"], "feed_title" => $line["feed_title"], "note" => $line["note"], @@ -736,7 +734,7 @@ class API extends Handler { "tags" => $tags, ); - $enclosures = Article::get_article_enclosures($line['id']); + $enclosures = Article::get_enclosures($line['id']); if ($include_attachments) $headline_row['attachments'] = $enclosures; diff --git a/classes/article.php b/classes/article.php index 5ea936985..00d9d09c5 100755 --- a/classes/article.php +++ b/classes/article.php @@ -352,145 +352,62 @@ class Article extends Handler_Protected { } } - static function format_article_enclosures($id, $always_display_enclosures, - $article_content, $hide_images = false) { - - $result = self::get_article_enclosures($id); - $rv = ''; + static function format_enclosures($id, + $always_display_enclosures, + $article_content, + $hide_images = false) { + + $enclosures = self::get_enclosures($id); + $rv = []; + $enclosures_formatted = ""; + + /*foreach ($enclosures as &$enc) { + array_push($enclosures, [ + "type" => $enc["content_type"], + "filename" => basename($enc["content_url"]), + "url" => $enc["content_url"], + "title" => $enc["title"], + "width" => (int) $enc["width"], + "height" => (int) $enc["height"] + ]); + }*/ PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_FORMAT_ENCLOSURES, - function ($result) use (&$rv) { + function ($result) use (&$enclosures_formatted, &$enclosures) { if (is_array($result)) { - $rv = $result[0]; - $result = $result[1]; + $enclosures_formatted = $result[0]; + $enclosures = $result[1]; } else { - $rv = $result; + $enclosures_formatted = $result; } }, - $rv, $result, $id, $always_display_enclosures, $article_content, $hide_images); - - if ($rv === '' && !empty($result)) { - $entries_html = array(); - $entries = array(); - $entries_inline = array(); - - foreach ($result as $line) { - - PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_ENCLOSURE_ENTRY, - function($result) use (&$line) { - $line = $result; - }, - $line, $id); - - $url = $line["content_url"]; - $ctype = $line["content_type"]; - $title = $line["title"]; - $width = $line["width"]; - $height = $line["height"]; - - if (!$ctype) $ctype = __("unknown type"); - - //$filename = substr($url, strrpos($url, "/")+1); - $filename = basename($url); - - $player = format_inline_player($url, $ctype); - - if ($player) array_push($entries_inline, $player); - -# $entry .= " " . -# $filename . " (" . $ctype . ")" . ""; - - $entry = "
$filename ($ctype)
"; - - array_push($entries_html, $entry); - - $entry = array(); - - $entry["type"] = $ctype; - $entry["filename"] = $filename; - $entry["url"] = $url; - $entry["title"] = $title; - $entry["width"] = $width; - $entry["height"] = $height; + $enclosures_formatted, $enclosures, $id, $always_display_enclosures, $article_content, $hide_images); - array_push($entries, $entry); - } - - if ($_SESSION['uid'] && !get_pref("STRIP_IMAGES") && !$_SESSION["bw_limit"]) { - if ($always_display_enclosures || - !preg_match("/chain_hooks_callback(PluginHost::HOOK_RENDER_ENCLOSURE, - function($result) use (&$retval) { - $retval = $result; - }, - $entry, $hide_images); - - if (!empty($retval)) { - $rv .= $retval; - } else { - - if (preg_match("/image/", $entry["type"])) { - - if (!$hide_images) { - $encsize = ''; - if ($entry['height'] > 0) - $encsize .= ' height="' . intval($entry['height']) . '"'; - if ($entry['width'] > 0) - $encsize .= ' width="' . intval($entry['width']) . '"'; - $rv .= "

\"".htmlspecialchars($entry["filename"])."\"

"; - } else { - $rv .= "

" .htmlspecialchars($entry["url"]) . "

"; - } - - if ($entry['title']) { - $rv.= "
${entry['title']}
"; - } - } - } - } - } - } - - if (count($entries_inline) > 0) { - //$rv .= "
"; - foreach ($entries_inline as $entry) { $rv .= $entry; }; - $rv .= "
"; - } + if (!empty($enclosures_formatted)) { + $rv['formatted'] = $enclosures_formatted; + return $rv; + } - $rv .= "
". - "" . __('Attachments').""; + $rv['can_inline'] = isset($_SESSION["uid"]) && + empty($_SESSION["bw_limit"]) && + !get_pref("STRIP_IMAGES") && + ($always_display_enclosures || !preg_match("/"; + $rv['inline_text_only'] = $hide_images && $rv['can_inline']; - foreach ($entries as $entry) { - if ($entry["title"]) - $title = " — " . truncate_string($entry["title"], 30); - else - $title = ""; + $rv['entries'] = []; - if ($entry["filename"]) - $filename = truncate_middle(htmlspecialchars($entry["filename"]), 60); - else - $filename = ""; + foreach ($enclosures as $enc) { - $rv .= "
".$filename . $title."
"; + // this is highly approximate + $enc["filename"] = basename($enc["content_url"]); - }; - - $rv .= "
"; - $rv .= ""; + PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_ENCLOSURE_ENTRY, + function ($result) use (&$enc) { + $enc = $result; + }, + $enc, $id); + array_push($rv['entries'], $enc); } return $rv; @@ -613,7 +530,7 @@ class Article extends Handler_Protected { } } - static function get_article_enclosures($id) { + static function get_enclosures($id) { $pdo = Db::pdo(); @@ -625,7 +542,7 @@ class Article extends Handler_Protected { $cache = new DiskCache("images"); - while ($line = $sth->fetch()) { + while ($line = $sth->fetch(PDO::FETCH_ASSOC)) { if ($cache->exists(sha1($line["content_url"]))) { $line["content_url"] = $cache->getUrl(sha1($line["content_url"])); diff --git a/classes/feeds.php b/classes/feeds.php index ba320b52f..d49fe7698 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -283,8 +283,10 @@ class Feeds extends Handler_Protected { $this->mark_timestamp(" pre-enclosures"); - $line["enclosures"] = Article::format_article_enclosures($id, $line["always_display_enclosures"], - $line["content"], $line["hide_images"]); + $line["enclosures"] = Article::format_enclosures($id, + $line["always_display_enclosures"], + $line["content"], + $line["hide_images"]); $this->mark_timestamp(" enclosures"); diff --git a/classes/handler/public.php b/classes/handler/public.php index 79f3a9e6c..0613e9a28 100755 --- a/classes/handler/public.php +++ b/classes/handler/public.php @@ -131,7 +131,7 @@ class Handler_Public extends Handler { $tpl->addBlock('category'); } - $enclosures = Article::get_article_enclosures($line["id"]); + $enclosures = Article::get_enclosures($line["id"]); if (count($enclosures) > 0) { foreach ($enclosures as $e) { @@ -218,7 +218,7 @@ class Handler_Public extends Handler { } } - $enclosures = Article::get_article_enclosures($line["id"]); + $enclosures = Article::get_enclosures($line["id"]); if (count($enclosures) > 0) { $article['enclosures'] = array(); @@ -356,9 +356,7 @@ class Handler_Public extends Handler { $line['content'] = DiskCache::rewriteUrls($line['content']); - $enclosures = Article::get_article_enclosures($line["id"]); - - header("Content-Type: text/html"); + header("Content-Type: text/html"); $rv .= " @@ -392,6 +390,7 @@ class Handler_Public extends Handler { $rv .= ""; + $enclosures = Article::get_enclosures($line["id"]); list ($og_image, $og_stream) = Article::get_article_image($enclosures, $line['content'], $line["site_url"]); if ($og_image) { @@ -436,10 +435,10 @@ class Handler_Public extends Handler { $rv .= $line["content"]; - $rv .= Article::format_article_enclosures($id, + /* $rv .= Article::format_article_enclosures($id, $line["always_display_enclosures"], $line["content"], - $line["hide_images"]); + $line["hide_images"]); */ $rv .= ""; # content diff --git a/classes/rpc.php b/classes/rpc.php index f6b57775d..e0753a08e 100755 --- a/classes/rpc.php +++ b/classes/rpc.php @@ -192,9 +192,7 @@ class RPC extends Handler_Protected { } function sanityCheck() { - $_SESSION["hasAudio"] = clean($_REQUEST["hasAudio"]) === "true"; $_SESSION["hasSandbox"] = clean($_REQUEST["hasSandbox"]) === "true"; - $_SESSION["hasMp3"] = clean($_REQUEST["hasMp3"]) === "true"; $_SESSION["clientTzOffset"] = clean($_REQUEST["clientTzOffset"]); $reply = array(); diff --git a/include/controls.php b/include/controls.php index e6678db9a..f706931db 100755 --- a/include/controls.php +++ b/include/controls.php @@ -298,37 +298,6 @@ function print_error($msg) { return print format_error($msg); } -function format_inline_player($url, $ctype) { - - $entry = ""; - - $url = htmlspecialchars($url); - - if (strpos($ctype, "audio/") === 0) { - - $entry .= "
"; - - if ($_SESSION["hasAudio"] && (strpos($ctype, "ogg") !== false || - $_SESSION["hasMp3"])) { - - $entry .= " "; - - } - - if ($entry) $entry .= "" . basename($url) . ""; - - $entry .= "
"; - - return $entry; - - } - - return ""; -} - function print_label_select($name, $value, $attributes = "") { $pdo = Db::pdo(); diff --git a/js/App.js b/js/App.js index 0a72d1b12..3a31438c5 100644 --- a/js/App.js +++ b/js/App.js @@ -586,6 +586,10 @@ const App = { isPrefs() { return this.is_prefs; }, + audioCanPlay: function(ctype) { + const a = document.createElement('audio'); + return a.canPlayType(ctype); + }, init: function(parser, is_prefs) { this.is_prefs = is_prefs; window.onerror = this.Error.onWindowError; @@ -604,17 +608,11 @@ const App = { this.initHotkeyActions(); this.enableCsrfSupport(); - const a = document.createElement('audio'); - const hasAudio = !!a.canPlayType; - const hasSandbox = "sandbox" in document.createElement("iframe"); - const hasMp3 = !!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, '')); - const clientTzOffset = new Date().getTimezoneOffset() * 60; - const params = { - op: "rpc", method: "sanityCheck", hasAudio: hasAudio, - hasMp3: hasMp3, - clientTzOffset: clientTzOffset, - hasSandbox: hasSandbox + op: "rpc", + method: "sanityCheck", + clientTzOffset: new Date().getTimezoneOffset() * 60, + hasSandbox: "sandbox" in document.createElement("iframe") }; xhrPost("backend.php", params, (transport) => { diff --git a/js/Article.js b/js/Article.js index f8b0415b9..efe33bc99 100644 --- a/js/Article.js +++ b/js/Article.js @@ -140,6 +140,62 @@ const Article = { Headlines.toggleUnread(id, 0); }, + renderEnclosures: function (enclosures) { + + // enclosure list was handled by backend (HOOK_FORMAT_ENCLOSURES) + if (enclosures.formatted) + return enclosures.formatted; + + return ` + ${enclosures.can_inline ? + `
+ ${enclosures.entries.map((enc) => { + if (!enclosures.inline_text_only) { + if (enc.content_type && enc.content_type.indexOf("image/") != -1) { + return `

+ +

` + } else if (enc.content_type && enc.content_type.indexOf("audio/") != -1 && App.audioCanPlay(enc.content_type)) { + return `

+ +

+ `; + } else { + return `

+ ${App.escapeHtml(enc.content_url)} +

` + } + } else { + return `

+ ${App.escapeHtml(enc.content_url)} +

` + } + }).join("")} +
` : ''} + ${enclosures.entries.length > 0 ? + `
+ ${__('Attachments')} +
+ ${enclosures.entries.map((enc) => ` +
+ ${enc.title ? enc.title : enc.filename} +
+ `).join("")} +
+
` : ''} + ` + }, render: function (article) { App.cleanupMemory("content-insert"); @@ -241,7 +297,7 @@ const Article = {
${hl.note}
${hl.content} - ${hl.enclosures} + ${Article.renderEnclosures(hl.enclosures)}
`; diff --git a/js/Headlines.js b/js/Headlines.js index 94541b974..dadf79c1a 100755 --- a/js/Headlines.js +++ b/js/Headlines.js @@ -488,7 +488,7 @@ const Headlines = {
- ${hl.enclosures} + ${Article.renderEnclosures(hl.enclosures)}