From 9b674e7e9390d19c1a9686710d78164a41ad31d1 Mon Sep 17 00:00:00 2001 From: maTh Date: Sun, 20 Nov 2022 15:10:33 +0100 Subject: Improved: show bigmarkasread button only, when there are unread articles (#4681) * function toggle_bigMarkAsRead_button() * nothing_to_load text outside of bigmarkasread button * improved * fix * Update p/scripts/main.js Co-authored-by: Alexandre Alapetite Co-authored-by: Alexandre Alapetite --- app/views/helpers/stream-footer.phtml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'app/views') diff --git a/app/views/helpers/stream-footer.phtml b/app/views/helpers/stream-footer.phtml index ebce4d852..f37ba59d6 100755 --- a/app/views/helpers/stream-footer.phtml +++ b/app/views/helpers/stream-footer.phtml @@ -30,19 +30,20 @@ if ($hasAccess) { ?> +
-
-
-
+
-- cgit v1.2.3 From c05e931d5ed2ce315e9556db9ebf6afd9918f6fc Mon Sep 17 00:00:00 2001 From: maTh Date: Sat, 26 Nov 2022 11:31:30 +0100 Subject: Deleted: bookmark.svg (#4897) * delete bookmark.svg * optimize Pafat theme --- app/Models/Themes.php | 1 - app/layout/aside_feed.phtml | 2 +- app/views/configure/display.phtml | 2 +- p/themes/BlueLagoon/icons/bookmark.svg | 3 --- p/themes/Pafat/icons/all.svg | 12 +++++------- p/themes/Pafat/icons/bookmark.svg | 5 ----- p/themes/Pafat/pafat.css | 1 + p/themes/Pafat/pafat.rtl.css | 1 + p/themes/Screwdriver/icons/bookmark.svg | 5 ----- p/themes/Swage/icons/bookmark.svg | 6 ------ p/themes/icons/bookmark.svg | 5 ----- 11 files changed, 9 insertions(+), 34 deletions(-) delete mode 100644 p/themes/BlueLagoon/icons/bookmark.svg delete mode 100644 p/themes/Pafat/icons/bookmark.svg delete mode 100644 p/themes/Screwdriver/icons/bookmark.svg delete mode 100644 p/themes/Swage/icons/bookmark.svg delete mode 100644 p/themes/icons/bookmark.svg (limited to 'app/views') diff --git a/app/Models/Themes.php b/app/Models/Themes.php index d652ada5b..86125c5f5 100644 --- a/app/Models/Themes.php +++ b/app/Models/Themes.php @@ -79,7 +79,6 @@ class FreshRSS_Themes extends Minz_Model { static $alts = array( 'add' => '➕', //✚ 'all' => '☰', - 'bookmark' => '✨', //★ 'bookmark-add' => '➕', //✚ 'bookmark-tag' => '📑', 'category' => '🗂️', //☷ diff --git a/app/layout/aside_feed.phtml b/app/layout/aside_feed.phtml index 3c4f1ec2e..bb9d678dc 100644 --- a/app/layout/aside_feed.phtml +++ b/app/layout/aside_feed.phtml @@ -37,7 +37,7 @@
  • - + diff --git a/app/views/configure/display.phtml b/app/views/configure/display.phtml index e3e18f5a0..d49986981 100644 --- a/app/views/configure/display.phtml +++ b/app/views/configure/display.phtml @@ -126,7 +126,7 @@   - + diff --git a/p/themes/BlueLagoon/icons/bookmark.svg b/p/themes/BlueLagoon/icons/bookmark.svg deleted file mode 100644 index 898488038..000000000 --- a/p/themes/BlueLagoon/icons/bookmark.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/p/themes/Pafat/icons/all.svg b/p/themes/Pafat/icons/all.svg index 14fa80366..1c7ba3ffe 100644 --- a/p/themes/Pafat/icons/all.svg +++ b/p/themes/Pafat/icons/all.svg @@ -1,7 +1,5 @@ - - - - - - - \ No newline at end of file + + + + + diff --git a/p/themes/Pafat/icons/bookmark.svg b/p/themes/Pafat/icons/bookmark.svg deleted file mode 100644 index 70d0c81fb..000000000 --- a/p/themes/Pafat/icons/bookmark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/p/themes/Pafat/pafat.css b/p/themes/Pafat/pafat.css index d64521573..fe8770c88 100644 --- a/p/themes/Pafat/pafat.css +++ b/p/themes/Pafat/pafat.css @@ -476,6 +476,7 @@ a.btn { line-height: 1; } +.tree-folder-title > .icon, .tree-folder-title .title .icon { filter: brightness(2.5); } diff --git a/p/themes/Pafat/pafat.rtl.css b/p/themes/Pafat/pafat.rtl.css index 55e255369..60877e1ad 100644 --- a/p/themes/Pafat/pafat.rtl.css +++ b/p/themes/Pafat/pafat.rtl.css @@ -476,6 +476,7 @@ a.btn { line-height: 1; } +.tree-folder-title > .icon, .tree-folder-title .title .icon { filter: brightness(2.5); } diff --git a/p/themes/Screwdriver/icons/bookmark.svg b/p/themes/Screwdriver/icons/bookmark.svg deleted file mode 100644 index edf5a02db..000000000 --- a/p/themes/Screwdriver/icons/bookmark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/p/themes/Swage/icons/bookmark.svg b/p/themes/Swage/icons/bookmark.svg deleted file mode 100644 index 09bf263fd..000000000 --- a/p/themes/Swage/icons/bookmark.svg +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/p/themes/icons/bookmark.svg b/p/themes/icons/bookmark.svg deleted file mode 100644 index 63a44908f..000000000 --- a/p/themes/icons/bookmark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file -- cgit v1.2.3 From 6261dc9cf41aaaa0eb2a05fbe81bc107ab91bbdd Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Tue, 29 Nov 2022 15:27:32 +0100 Subject: User-defined time zone (#4906) * User-defined time zone #fix https://github.com/FreshRSS/FreshRSS/issues/2754 * Update app/i18n/nl/conf.php Co-authored-by: Frans de Jonge * Timezone when creating a new user Co-authored-by: Frans de Jonge --- app/Controllers/configureController.php | 1 + app/Controllers/userController.php | 1 + app/FreshRSS.php | 3 +++ app/Models/UserConfiguration.php | 1 + app/i18n/cz/conf.php | 1 + app/i18n/de/conf.php | 1 + app/i18n/el/conf.php | 1 + app/i18n/en-us/conf.php | 1 + app/i18n/en/conf.php | 1 + app/i18n/es/conf.php | 1 + app/i18n/fr/conf.php | 1 + app/i18n/he/conf.php | 1 + app/i18n/id/conf.php | 1 + app/i18n/it/conf.php | 1 + app/i18n/ja/conf.php | 1 + app/i18n/ko/conf.php | 1 + app/i18n/nl/conf.php | 1 + app/i18n/oc/conf.php | 1 + app/i18n/pl/conf.php | 1 + app/i18n/pt-br/conf.php | 1 + app/i18n/ru/conf.php | 1 + app/i18n/sk/conf.php | 1 + app/i18n/tr/conf.php | 1 + app/i18n/zh-cn/conf.php | 1 + app/i18n/zh-tw/conf.php | 1 + app/views/auth/register.phtml | 12 ++++++++++++ app/views/configure/display.phtml | 19 +++++++++++++++++++ app/views/user/manage.phtml | 16 ++++++++++++++-- config-user.default.php | 2 ++ 29 files changed, 74 insertions(+), 2 deletions(-) (limited to 'app/views') diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php index 613bacade..926ab2272 100755 --- a/app/Controllers/configureController.php +++ b/app/Controllers/configureController.php @@ -42,6 +42,7 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController { public function displayAction() { if (Minz_Request::isPost()) { FreshRSS_Context::$user_conf->language = Minz_Request::param('language', 'en'); + FreshRSS_Context::$user_conf->timezone = Minz_Request::param('timezone', ''); FreshRSS_Context::$user_conf->theme = Minz_Request::param('theme', FreshRSS_Themes::$defaultTheme); FreshRSS_Context::$user_conf->content_width = Minz_Request::param('content_width', 'thin'); FreshRSS_Context::$user_conf->topline_read = Minz_Request::param('topline_read', false); diff --git a/app/Controllers/userController.php b/app/Controllers/userController.php index 06dbab9fa..55b4ca7cb 100644 --- a/app/Controllers/userController.php +++ b/app/Controllers/userController.php @@ -344,6 +344,7 @@ class FreshRSS_user_Controller extends FreshRSS_ActionController { $ok = self::createUser($new_user_name, $email, $passwordPlain, array( 'language' => Minz_Request::param('new_user_language', FreshRSS_Context::$user_conf->language), + 'timezone' => Minz_Request::param('new_user_timezone', ''), 'is_admin' => Minz_Request::paramBoolean('new_user_is_admin'), 'enabled' => true, )); diff --git a/app/FreshRSS.php b/app/FreshRSS.php index 602c46658..02460af69 100644 --- a/app/FreshRSS.php +++ b/app/FreshRSS.php @@ -99,6 +99,9 @@ class FreshRSS extends Minz_FrontController { Minz_Session::_param('language', $language); Minz_Translate::init($language); + + $timezone = isset(FreshRSS_Context::$user_conf) ? FreshRSS_Context::$user_conf->timezone : ''; + date_default_timezone_set($timezone != '' ? $timezone : '' . ini_get('date.timezone')); } private static function getThemeFileUrl($theme_id, $filename) { diff --git a/app/Models/UserConfiguration.php b/app/Models/UserConfiguration.php index b8b023d79..157737cb8 100644 --- a/app/Models/UserConfiguration.php +++ b/app/Models/UserConfiguration.php @@ -28,6 +28,7 @@ * @property-read string $is_admin * @property int|null $keep_history_default * @property string $language + * @property string $timezone * @property bool $lazyload * @property string $mail_login * @property bool $mark_updated_article_unread diff --git a/app/i18n/cz/conf.php b/app/i18n/cz/conf.php index 7b603555c..7b0b85465 100644 --- a/app/i18n/cz/conf.php +++ b/app/i18n/cz/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Na výšku', 'square' => 'Čtverec', ), + 'timezone' => 'Time zone', // TODO 'title' => 'Zobrazení', 'width' => array( 'content' => 'Šířka obsahu', diff --git a/app/i18n/de/conf.php b/app/i18n/de/conf.php index 5e9cdb36e..52826353b 100644 --- a/app/i18n/de/conf.php +++ b/app/i18n/de/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Hochformat', 'square' => 'Quadrat', ), + 'timezone' => 'Time zone', // TODO 'title' => 'Anzeige', 'width' => array( 'content' => 'Inhaltsbreite', diff --git a/app/i18n/el/conf.php b/app/i18n/el/conf.php index 98f559d18..a068282ea 100644 --- a/app/i18n/el/conf.php +++ b/app/i18n/el/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Portrait', // TODO 'square' => 'Square', // TODO ), + 'timezone' => 'Time zone', // TODO 'title' => 'Display', // TODO 'width' => array( 'content' => 'Content width', // TODO diff --git a/app/i18n/en-us/conf.php b/app/i18n/en-us/conf.php index 8330e4970..8a572def3 100644 --- a/app/i18n/en-us/conf.php +++ b/app/i18n/en-us/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Portrait', // IGNORE 'square' => 'Square', // IGNORE ), + 'timezone' => 'Time zone', // IGNORE 'title' => 'Display', // IGNORE 'width' => array( 'content' => 'Content width', // IGNORE diff --git a/app/i18n/en/conf.php b/app/i18n/en/conf.php index fe03499ea..d6633f981 100644 --- a/app/i18n/en/conf.php +++ b/app/i18n/en/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Portrait', 'square' => 'Square', ), + 'timezone' => 'Time zone', 'title' => 'Display', 'width' => array( 'content' => 'Content width', diff --git a/app/i18n/es/conf.php b/app/i18n/es/conf.php index c91b0205c..8c77dcd7e 100755 --- a/app/i18n/es/conf.php +++ b/app/i18n/es/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Retrato', 'square' => 'Cuadrado', ), + 'timezone' => 'Time zone', // TODO 'title' => 'Visualización', 'width' => array( 'content' => 'Ancho de contenido', diff --git a/app/i18n/fr/conf.php b/app/i18n/fr/conf.php index 61306289c..71902d96d 100644 --- a/app/i18n/fr/conf.php +++ b/app/i18n/fr/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Portrait', // IGNORE 'square' => 'Carrée', ), + 'timezone' => 'Fuseau horaire', 'title' => 'Affichage', 'width' => array( 'content' => 'Largeur du contenu', diff --git a/app/i18n/he/conf.php b/app/i18n/he/conf.php index ad479db44..ec322fddf 100644 --- a/app/i18n/he/conf.php +++ b/app/i18n/he/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Portrait', // TODO 'square' => 'Square', // TODO ), + 'timezone' => 'Time zone', // TODO 'title' => 'תצוגה', 'width' => array( 'content' => 'רוחב התוכן', diff --git a/app/i18n/id/conf.php b/app/i18n/id/conf.php index b8a5b4fc1..f46347fe2 100644 --- a/app/i18n/id/conf.php +++ b/app/i18n/id/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Portrait', // TODO 'square' => 'Square', // TODO ), + 'timezone' => 'Time zone', // TODO 'title' => 'Display', // TODO 'width' => array( 'content' => 'Content width', // TODO diff --git a/app/i18n/it/conf.php b/app/i18n/it/conf.php index 4597687cc..8efe6be41 100644 --- a/app/i18n/it/conf.php +++ b/app/i18n/it/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Ritratto', 'square' => 'Squadrata', ), + 'timezone' => 'Time zone', // TODO 'title' => 'Visualizzazione', 'width' => array( 'content' => 'Larghezza contenuto', diff --git a/app/i18n/ja/conf.php b/app/i18n/ja/conf.php index 5e9aabfa2..f84354c36 100644 --- a/app/i18n/ja/conf.php +++ b/app/i18n/ja/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'ポートレート', 'square' => '四角', ), + 'timezone' => 'Time zone', // TODO 'title' => 'ディスプレイ', 'width' => array( 'content' => 'コンテンツ幅', diff --git a/app/i18n/ko/conf.php b/app/i18n/ko/conf.php index 279f2f4ad..95fda6969 100644 --- a/app/i18n/ko/conf.php +++ b/app/i18n/ko/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => '세로 방향', 'square' => '정사각형', ), + 'timezone' => 'Time zone', // TODO 'title' => '표시', 'width' => array( 'content' => '내용 표시 너비', diff --git a/app/i18n/nl/conf.php b/app/i18n/nl/conf.php index 8b3d597b1..261c3aa33 100644 --- a/app/i18n/nl/conf.php +++ b/app/i18n/nl/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Staand', 'square' => 'Vierkant', ), + 'timezone' => 'Tijdzone', 'title' => 'Opmaak', 'width' => array( 'content' => 'Inhoud breedte', diff --git a/app/i18n/oc/conf.php b/app/i18n/oc/conf.php index c1834e9aa..9f157a497 100644 --- a/app/i18n/oc/conf.php +++ b/app/i18n/oc/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Retrach', 'square' => 'Carrat', ), + 'timezone' => 'Time zone', // TODO 'title' => 'Afichatge', 'width' => array( 'content' => 'Largor del contengut', diff --git a/app/i18n/pl/conf.php b/app/i18n/pl/conf.php index 31b0d238c..3349bbf53 100644 --- a/app/i18n/pl/conf.php +++ b/app/i18n/pl/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Portret', 'square' => 'Kwadrat', ), + 'timezone' => 'Time zone', // TODO 'title' => 'Wyświetlanie', 'width' => array( 'content' => 'Rozmiar treści', diff --git a/app/i18n/pt-br/conf.php b/app/i18n/pt-br/conf.php index b925aee21..bcf9fbd2f 100644 --- a/app/i18n/pt-br/conf.php +++ b/app/i18n/pt-br/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Modo retrato', 'square' => 'Modo quadrado', ), + 'timezone' => 'Time zone', // TODO 'title' => 'Exibição', 'width' => array( 'content' => 'Largura do conteúdo', diff --git a/app/i18n/ru/conf.php b/app/i18n/ru/conf.php index c0d25aec1..98e6f5003 100644 --- a/app/i18n/ru/conf.php +++ b/app/i18n/ru/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Вертикальный', 'square' => 'Квадратный', ), + 'timezone' => 'Time zone', // TODO 'title' => 'Отображение', 'width' => array( 'content' => 'Ширина содержимого', diff --git a/app/i18n/sk/conf.php b/app/i18n/sk/conf.php index 7efc3a75d..822de7b09 100644 --- a/app/i18n/sk/conf.php +++ b/app/i18n/sk/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Nastojato', 'square' => 'Štvorec', ), + 'timezone' => 'Time zone', // TODO 'title' => 'Zobraziť', 'width' => array( 'content' => 'Šírka obsahu', diff --git a/app/i18n/tr/conf.php b/app/i18n/tr/conf.php index 7220d6670..14eb152c3 100644 --- a/app/i18n/tr/conf.php +++ b/app/i18n/tr/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => 'Portre', 'square' => 'Kare', ), + 'timezone' => 'Time zone', // TODO 'title' => 'Görünüm', 'width' => array( 'content' => 'İçerik genişliği', diff --git a/app/i18n/zh-cn/conf.php b/app/i18n/zh-cn/conf.php index 3a1282a12..a4d293aeb 100644 --- a/app/i18n/zh-cn/conf.php +++ b/app/i18n/zh-cn/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => '纵向', 'square' => '方形', ), + 'timezone' => 'Time zone', // TODO 'title' => '显示', 'width' => array( 'content' => '内容宽度', diff --git a/app/i18n/zh-tw/conf.php b/app/i18n/zh-tw/conf.php index 15fabaa40..61ba44151 100644 --- a/app/i18n/zh-tw/conf.php +++ b/app/i18n/zh-tw/conf.php @@ -57,6 +57,7 @@ return array( 'portrait' => '肖像', 'square' => '方塊', ), + 'timezone' => 'Time zone', // TODO 'title' => '顯示', 'width' => array( 'content' => '內容寬度', diff --git a/app/views/auth/register.phtml b/app/views/auth/register.phtml index a56eff3ee..66c4a1ccb 100644 --- a/app/views/auth/register.phtml +++ b/app/views/auth/register.phtml @@ -15,6 +15,18 @@
    +
    + + +
    +
    +
    + +
    + +
    +
    +
    diff --git a/app/views/user/manage.phtml b/app/views/user/manage.phtml index 0d01d33d7..22a1a4d03 100644 --- a/app/views/user/manage.phtml +++ b/app/views/user/manage.phtml @@ -15,8 +15,6 @@ - -
    @@ -30,6 +28,20 @@
    +
    + +
    + +
    +
    +
    diff --git a/config-user.default.php b/config-user.default.php index f7759396a..e1f332bf2 100644 --- a/config-user.default.php +++ b/config-user.default.php @@ -7,6 +7,8 @@ return array ( 'enabled' => true, 'is_admin' => false, 'language' => 'en', + // A timezone identifier such as 'Europe/Paris' https://php.net/timezones or blank for server default + 'timezone' => '', 'archiving' => [ 'keep_period' => 'P3M', 'keep_max' => 200, -- cgit v1.2.3 From 8f9c4143fcc133f28db4c3f618649fb1170e33b4 Mon Sep 17 00:00:00 2001 From: Alexandre Alapetite Date: Fri, 6 Jan 2023 19:53:43 +0100 Subject: Better enclosures (#4944) * Better enclosures #fix https://github.com/FreshRSS/FreshRSS/issues/4702 Improvement of https://github.com/FreshRSS/FreshRSS/pull/2898 * A few fixes * Better enclosure titles * Improve thumbnails * Implement thumbnail for HTML+XPath * Avoid duplicate enclosures #fix https://github.com/FreshRSS/FreshRSS/issues/1668 * Fix regex * Add basic support for media:credit And use
    for enclosures * Fix link encoding + simplify code * Fix some SimplePie bugs Encoding errors in enclosure links * Remove debugging syslog * Remove debugging syslog * SimplePie fix multiple RSS2 enclosures #fix https://github.com/FreshRSS/FreshRSS/issues/4974 * Improve thumbnails * Performance with yield Avoid generating all enclosures if not used * API keep providing enclosures inside content Clients are typically not showing the enclosures to the users (tested with News+, FeedMe, Readrops, Fluent Reader Lite) * Lint * Fix API output enclosure * Fix API content strcut * API tolerate enclosures without a type --- app/Controllers/feedController.php | 2 +- app/Models/Entry.php | 167 ++++++++++++++++++---- app/Models/Feed.php | 73 ++++------ app/views/helpers/index/normal/entry_header.phtml | 5 +- app/views/index/normal.phtml | 2 +- app/views/index/reader.phtml | 2 +- app/views/index/rss.phtml | 22 ++- lib/SimplePie/SimplePie/Enclosure.php | 2 +- lib/SimplePie/SimplePie/Item.php | 25 ++-- 9 files changed, 211 insertions(+), 89 deletions(-) (limited to 'app/views') diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php index 319faece8..3ef3af67d 100755 --- a/app/Controllers/feedController.php +++ b/app/Controllers/feedController.php @@ -949,7 +949,7 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController { $this->view->htmlContent = $fullContent; } else { $this->view->selectorSuccess = false; - $this->view->htmlContent = $entry->content(); + $this->view->htmlContent = $entry->content(false); } } catch (Exception $e) { $this->view->fatalError = _t('feedback.sub.feed.selector_preview.http_error'); diff --git a/app/Models/Entry.php b/app/Models/Entry.php index 47fcf3b4a..ec7629253 100644 --- a/app/Models/Entry.php +++ b/app/Models/Entry.php @@ -67,7 +67,9 @@ class FreshRSS_Entry extends Minz_Model { $dao['content'] = ''; } if (!empty($dao['thumbnail'])) { - $dao['content'] .= '

    '; + $dao['attributes']['thumbnail'] = [ + 'url' => $dao['thumbnail'], + ]; } $entry = new FreshRSS_Entry( $dao['id_feed'] ?? 0, @@ -116,15 +118,117 @@ class FreshRSS_Entry extends Minz_Model { return $this->authors; } } - public function content(): string { - return $this->content; + + /** + * Basic test without ambition to catch all cases such as unquoted addresses, variants of entities, HTML comments, etc. + */ + private static function containsLink(string $html, string $link): bool { + return preg_match('/(?P[\'"])' . preg_quote($link, '/') . '(?P=delim)/', $html) == 1; + } + + private static function enclosureIsImage(array $enclosure): bool { + $elink = $enclosure['url'] ?? ''; + $length = $enclosure['length'] ?? 0; + $medium = $enclosure['medium'] ?? ''; + $mime = $enclosure['type'] ?? ''; + + return $elink != '' && $medium === 'image' || strpos($mime, 'image') === 0 || + ($mime == '' && $length == 0 && preg_match('/[.](avif|gif|jpe?g|png|svg|webp)$/i', $elink)); } - /** @return array> */ - public function enclosures(bool $searchBodyImages = false): array { - $results = []; + /** + * @param bool $withEnclosures Set to true to include the enclosures in the returned HTML, false otherwise. + * @param bool $allowDuplicateEnclosures Set to false to remove obvious enclosure duplicates (based on simple string comparison), true otherwise. + * @return string HTML content + */ + public function content(bool $withEnclosures = true, bool $allowDuplicateEnclosures = false): string { + if (!$withEnclosures) { + return $this->content; + } + + $content = $this->content; + + $thumbnail = $this->attributes('thumbnail'); + if (!empty($thumbnail['url'])) { + $elink = $thumbnail['url']; + if ($allowDuplicateEnclosures || !self::containsLink($content, $elink)) { + $content .= << +

    + +

    +
    +HTML; + } + } + + $attributeEnclosures = $this->attributes('enclosures'); + if (empty($attributeEnclosures)) { + return $content; + } + + foreach ($attributeEnclosures as $enclosure) { + $elink = $enclosure['url'] ?? ''; + if ($elink == '') { + continue; + } + if (!$allowDuplicateEnclosures && self::containsLink($content, $elink)) { + continue; + } + $credit = $enclosure['credit'] ?? ''; + $description = $enclosure['description'] ?? ''; + $length = $enclosure['length'] ?? 0; + $medium = $enclosure['medium'] ?? ''; + $mime = $enclosure['type'] ?? ''; + $thumbnails = $enclosure['thumbnails'] ?? []; + $etitle = $enclosure['title'] ?? ''; + + $content .= '
    '; + + foreach ($thumbnails as $thumbnail) { + $content .= '

    '; + } + + if (self::enclosureIsImage($enclosure)) { + $content .= '

    '; + } elseif ($medium === 'audio' || strpos($mime, 'audio') === 0) { + $content .= '

    💾

    '; + } elseif ($medium === 'video' || strpos($mime, 'video') === 0) { + $content .= '

    💾

    '; + } else { //e.g. application, text, unknown + $content .= '

    💾

    '; + } + + if ($credit != '') { + $content .= '

    © ' . $credit . '

    '; + } + if ($description != '') { + $content .= '
    ' . $description . '
    '; + } + $content .= "
    \n"; + } + + return $content; + } + + /** @return iterable> */ + public function enclosures(bool $searchBodyImages = false) { + $attributeEnclosures = $this->attributes('enclosures'); + if (is_array($attributeEnclosures)) { + // FreshRSS 1.20.1+: The enclosures are saved as attributes + yield from $attributeEnclosures; + } try { - $searchEnclosures = strpos($this->content, '

    content, 'query('//div[@class="enclosure"]/p[@class="enclosure-content"]/*[@src]'); foreach ($enclosures as $enclosure) { $result = [ @@ -148,7 +253,7 @@ class FreshRSS_Entry extends Minz_Model { case 'audio': $result['medium'] = 'audio'; break; } } - $results[] = $result; + yield Minz_Helper::htmlspecialchars_utf8($result); } } if ($searchBodyImages) { @@ -159,26 +264,31 @@ class FreshRSS_Entry extends Minz_Model { $src = $img->getAttribute('data-src'); } if ($src != null) { - $results[] = [ + $result = [ 'url' => $src, - 'alt' => $img->getAttribute('alt'), ]; + yield Minz_Helper::htmlspecialchars_utf8($result); } } } - return $results; } catch (Exception $ex) { - return $results; + Minz_Log::debug(__METHOD__ . ' ' . $ex->getMessage()); } } /** * @return array|null */ - public function thumbnail() { - foreach ($this->enclosures(true) as $enclosure) { - if (!empty($enclosure['url']) && empty($enclosure['type'])) { - return $enclosure; + public function thumbnail(bool $searchEnclosures = true) { + $thumbnail = $this->attributes('thumbnail'); + if (!empty($thumbnail['url'])) { + return $thumbnail; + } + if ($searchEnclosures) { + foreach ($this->enclosures(true) as $enclosure) { + if (self::enclosureIsImage($enclosure)) { + return $enclosure; + } } } return null; @@ -587,7 +697,7 @@ class FreshRSS_Entry extends Minz_Model { if ($entry) { // l’article existe déjà en BDD, en se contente de recharger ce contenu - $this->content = $entry->content(); + $this->content = $entry->content(false); } else { try { // The article is not yet in the database, so let’s fetch it @@ -629,7 +739,7 @@ class FreshRSS_Entry extends Minz_Model { 'guid' => $this->guid(), 'title' => $this->title(), 'author' => $this->authors(true), - 'content' => $this->content(), + 'content' => $this->content(false), 'link' => $this->link(), 'date' => $this->date(true), 'hash' => $this->hash(), @@ -677,7 +787,6 @@ class FreshRSS_Entry extends Minz_Model { 'published' => $this->date(true), // 'updated' => $this->date(true), 'title' => $this->title(), - 'summary' => ['content' => $this->content()], 'canonical' => [ ['href' => htmlspecialchars_decode($this->link(), ENT_QUOTES)], ], @@ -697,13 +806,16 @@ class FreshRSS_Entry extends Minz_Model { if ($mode === 'compat') { $item['title'] = escapeToUnicodeAlternative($this->title(), false); unset($item['alternate'][0]['type']); - if (mb_strlen($this->content(), 'UTF-8') > self::API_MAX_COMPAT_CONTENT_LENGTH) { - $item['summary']['content'] = mb_strcut($this->content(), 0, self::API_MAX_COMPAT_CONTENT_LENGTH, 'UTF-8'); - } - } elseif ($mode === 'freshrss') { + $item['summary'] = [ + 'content' => mb_strcut($this->content(true), 0, self::API_MAX_COMPAT_CONTENT_LENGTH, 'UTF-8'), + ]; + } else { + $item['content'] = [ + 'content' => $this->content(false), + ]; + } + if ($mode === 'freshrss') { $item['guid'] = $this->guid(); - unset($item['summary']); - $item['content'] = ['content' => $this->content()]; } if ($category != null && $mode !== 'freshrss') { $item['categories'][] = 'user/-/label/' . htmlspecialchars_decode($category->name(), ENT_QUOTES); @@ -718,10 +830,11 @@ class FreshRSS_Entry extends Minz_Model { } } foreach ($this->enclosures() as $enclosure) { - if (!empty($enclosure['url']) && !empty($enclosure['type'])) { + if (!empty($enclosure['url'])) { $media = [ 'href' => $enclosure['url'], - 'type' => $enclosure['type'], + 'type' => $enclosure['type'] ?? $enclosure['medium'] ?? + (self::enclosureIsImage($enclosure) ? 'image' : ''), ]; if (!empty($enclosure['length'])) { $media['length'] = intval($enclosure['length']); diff --git a/app/Models/Feed.php b/app/Models/Feed.php index 538814370..a63c2b3ea 100644 --- a/app/Models/Feed.php +++ b/app/Models/Feed.php @@ -502,61 +502,46 @@ class FreshRSS_Feed extends Minz_Model { $content = html_only_entity_decode($item->get_content()); - if ($item->get_enclosures() != null) { - $elinks = array(); + $attributeThumbnail = $item->get_thumbnail() ?? []; + if (empty($attributeThumbnail['url'])) { + $attributeThumbnail['url'] = ''; + } + + $attributeEnclosures = []; + if (!empty($item->get_enclosures())) { foreach ($item->get_enclosures() as $enclosure) { $elink = $enclosure->get_link(); - if ($elink != '' && empty($elinks[$elink])) { - $content .= '

    '; - - if ($enclosure->get_title() != '') { - $content .= '

    ' . $enclosure->get_title() . '

    '; - } - - $enclosureContent = ''; - $elinks[$elink] = true; + if ($elink != '') { + $etitle = $enclosure->get_title() ?? ''; + $credit = $enclosure->get_credit() ?? null; + $description = $enclosure->get_description() ?? ''; $mime = strtolower($enclosure->get_type() ?? ''); $medium = strtolower($enclosure->get_medium() ?? ''); $height = $enclosure->get_height(); $width = $enclosure->get_width(); $length = $enclosure->get_length(); - if ($medium === 'image' || strpos($mime, 'image') === 0 || - ($mime == '' && $length == null && ($width != 0 || $height != 0 || preg_match('/[.](avif|gif|jpe?g|png|svg|webp)$/i', $elink)))) { - $enclosureContent .= '

    '; - } elseif ($medium === 'audio' || strpos($mime, 'audio') === 0) { - $enclosureContent .= '

    💾

    '; - } elseif ($medium === 'video' || strpos($mime, 'video') === 0) { - $enclosureContent .= '

    💾

    '; - } else { //e.g. application, text, unknown - $enclosureContent .= '

    💾

    '; - } - $thumbnailContent = ''; - if ($enclosure->get_thumbnails() != null) { + $attributeEnclosure = [ + 'url' => $elink, + ]; + if ($etitle != '') $attributeEnclosure['title'] = $etitle; + if ($credit != null) $attributeEnclosure['credit'] = $credit->get_name(); + if ($description != '') $attributeEnclosure['description'] = $description; + if ($mime != '') $attributeEnclosure['type'] = $mime; + if ($medium != '') $attributeEnclosure['medium'] = $medium; + if ($length != '') $attributeEnclosure['length'] = intval($length); + if ($height != '') $attributeEnclosure['height'] = intval($height); + if ($width != '') $attributeEnclosure['width'] = intval($width); + + if (!empty($enclosure->get_thumbnails())) { foreach ($enclosure->get_thumbnails() as $thumbnail) { - if (empty($elinks[$thumbnail])) { - $elinks[$thumbnail] = true; - $thumbnailContent .= '

    '; + if ($thumbnail !== $attributeThumbnail['url']) { + $attributeEnclosure['thumbnails'][] = $thumbnail; } } } - $content .= $thumbnailContent; - $content .= $enclosureContent; - - if ($enclosure->get_description() != '') { - $content .= '

    ' . $enclosure->get_description() . '

    '; - } - $content .= "
    \n"; + $attributeEnclosures[] = $attributeEnclosure; } } } @@ -586,6 +571,10 @@ class FreshRSS_Feed extends Minz_Model { ); $entry->_tags($tags); $entry->_feed($this); + if (!empty($attributeThumbnail['url'])) { + $entry->_attributes('thumbnail', $attributeThumbnail); + } + $entry->_attributes('enclosures', $attributeEnclosures); $entry->hash(); //Must be computed before loading full content $entry->loadCompleteContent(); // Optionally load full content for truncated feeds diff --git a/app/views/helpers/index/normal/entry_header.phtml b/app/views/helpers/index/normal/entry_header.phtml index 43eeb7f8a..92eacf617 100644 --- a/app/views/helpers/index/normal/entry_header.phtml +++ b/app/views/helpers/index/normal/entry_header.phtml @@ -42,8 +42,7 @@ ?>
  • entry->thumbnail(); if ($thumbnail != null): - ?> /> alt="" />
  • @@ -62,7 +61,7 @@ ?>
    entry->content()), 0, 500, 'UTF-8')) ?>
    entry->content(false)), 0, 500, 'UTF-8')) ?>
  •  
  • diff --git a/app/views/index/normal.phtml b/app/views/index/normal.phtml index 6f7c47677..847c307ab 100644 --- a/app/views/index/normal.phtml +++ b/app/views/index/normal.phtml @@ -162,7 +162,7 @@ $today = @strtotime('today');
    entry->content()) : $this->entry->content(); + echo $lazyload && $hidePosts ? lazyimg($this->entry->content(true)) : $this->entry->content(true); ?>
    show_author_date === 'f' || FreshRSS_Context::$user_conf->show_author_date === 'b'; diff --git a/app/views/index/reader.phtml b/app/views/index/reader.phtml index 5789f229b..a2ea0e989 100644 --- a/app/views/index/reader.phtml +++ b/app/views/index/reader.phtml @@ -136,7 +136,7 @@ $MAX_TAGS_DISPLAYED = FreshRSS_Context::$user_conf->show_tags_max;
    - content() ?> + content(true) ?>
    show_author_date === 'f' || FreshRSS_Context::$user_conf->show_author_date === 'b'; diff --git a/app/views/index/rss.phtml b/app/views/index/rss.phtml index 0b07a02f3..0b3dc7955 100755 --- a/app/views/index/rss.phtml +++ b/app/views/index/rss.phtml @@ -29,29 +29,41 @@ foreach ($this->entries as $item) { $authors = $item->authors(); if (is_array($authors)) { foreach ($authors as $author) { - echo "\t\t\t" , '', $author, '', "\n"; + echo "\t\t\t", '', $author, '', "\n"; } } $categories = $item->tags(); if (is_array($categories)) { foreach ($categories as $category) { - echo "\t\t\t" , '', $category, '', "\n"; + echo "\t\t\t", '', $category, '', "\n"; } } + $thumbnail = $item->thumbnail(false); + if (!empty($thumbnail['url'])) { + // https://www.rssboard.org/media-rss#media-thumbnails + echo "\t\t\t", '', "\n"; + } $enclosures = $item->enclosures(false); if (is_array($enclosures)) { foreach ($enclosures as $enclosure) { // https://www.rssboard.org/media-rss - echo "\t\t\t" , '', "\n"; + . '">' + . (empty($enclosure['title']) ? '' : '' . $enclosure['title'] . '') + . (empty($enclosure['credit']) ? '' : '' . $enclosure['credit'] . '') + . '', "\n"; } } ?> content(); + echo $item->content(false); ?>]]> date(true)) ?> id() > 0 ? $item->id() : $item->guid() ?> diff --git a/lib/SimplePie/SimplePie/Enclosure.php b/lib/SimplePie/SimplePie/Enclosure.php index cc0d038b5..04bade09f 100644 --- a/lib/SimplePie/SimplePie/Enclosure.php +++ b/lib/SimplePie/SimplePie/Enclosure.php @@ -627,7 +627,7 @@ class SimplePie_Enclosure { if ($this->link !== null) { - return urldecode($this->link); + return $this->link; } return null; diff --git a/lib/SimplePie/SimplePie/Item.php b/lib/SimplePie/SimplePie/Item.php index 2fb1d3284..1285fd536 100644 --- a/lib/SimplePie/SimplePie/Item.php +++ b/lib/SimplePie/SimplePie/Item.php @@ -427,7 +427,16 @@ class SimplePie_Item { if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail')) { - $this->data['thumbnail'] = $return[0]['attribs']['']; + $thumbnail = $return[0]['attribs']['']; + if (empty($thumbnail['url'])) + { + $this->data['thumbnail'] = null; + } + else + { + $thumbnail['url'] = $this->sanitize($thumbnail['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0])); + $this->data['thumbnail'] = $thumbnail; + } } else { @@ -2847,9 +2856,9 @@ class SimplePie_Item } } - if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure')) + foreach ($this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure') ?? [] as $enclosure) { - if (isset($enclosure[0]['attribs']['']['url'])) + if (isset($enclosure['attribs']['']['url'])) { // Attributes $bitrate = null; @@ -2867,15 +2876,15 @@ class SimplePie_Item $url = null; $width = null; - $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0])); + $url = $this->sanitize($enclosure['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure)); $url = $this->feed->sanitize->https_url($url); - if (isset($enclosure[0]['attribs']['']['type'])) + if (isset($enclosure['attribs']['']['type'])) { - $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); + $type = $this->sanitize($enclosure['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT); } - if (isset($enclosure[0]['attribs']['']['length'])) + if (isset($enclosure['attribs']['']['length'])) { - $length = intval($enclosure[0]['attribs']['']['length']); + $length = intval($enclosure['attribs']['']['length']); } // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor -- cgit v1.2.3 From bbe3eb8f41ca9c25d1619cda9609392ffc803146 Mon Sep 17 00:00:00 2001 From: Sadetdin EYILI Date: Mon, 9 Jan 2023 10:37:35 +0100 Subject: Lazy load logo on install, logo on header and theme thumbs in config slide (#4998) * feat: lazy load logo on install, logo on header and theme thumbs in config slide --- app/install.php | 4 ++-- app/layout/header.phtml | 8 ++++---- app/layout/simple.phtml | 2 +- app/views/configure/display.phtml | 2 +- p/index.html | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) (limited to 'app/views') diff --git a/app/install.php b/app/install.php index 48f39d25e..3163367f4 100644 --- a/app/install.php +++ b/app/install.php @@ -445,7 +445,7 @@ function printStep1() {

    - 🔃 + 🔃 diff --git a/app/layout/header.phtml b/app/layout/header.phtml index b9d5c0a13..45eb9a3ce 100644 --- a/app/layout/header.phtml +++ b/app/layout/header.phtml @@ -2,7 +2,7 @@
    logo_html == '') { ?> - + logo_html; @@ -18,7 +18,7 @@ - + @@ -83,7 +83,7 @@ - +

    - + $items */ @@ -29,8 +29,8 @@ level()) ?> -