From 498a957009abf833a550169ef1ed4b271a51faa4 Mon Sep 17 00:00:00 2001 From: Michael Date: Wed, 7 Dec 2022 07:02:04 +0000 Subject: [PATCH 1/2] The appearanxe of the link preview is now configurable --- src/Content/Text/BBCode.php | 18 +++++-- src/Model/Item.php | 7 ++- src/Model/Post/Media.php | 48 +++++++++++++------ src/Module/Settings/Display.php | 14 +++++- view/templates/settings/display.tpl | 1 + .../theme/frio/templates/settings/display.tpl | 1 + 6 files changed, 68 insertions(+), 21 deletions(-) diff --git a/src/Content/Text/BBCode.php b/src/Content/Text/BBCode.php index 06654b2911..ae21d05e13 100644 --- a/src/Content/Text/BBCode.php +++ b/src/Content/Text/BBCode.php @@ -68,6 +68,12 @@ class BBCode const TOP_ANCHOR = '
'; const BOTTOM_ANCHOR = '
'; + + const PREVIEW_NONE = 0; + const PREVIEW_NO_IMAGE = 1; + const PREVIEW_LARGE = 2; + const PREVIEW_SMALL = 3; + /** * Fetches attachment data that were generated the old way * @@ -654,7 +660,7 @@ class BBCode * @return string * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ - public static function convertAttachment(string $text, int $simplehtml = self::INTERNAL, bool $tryoembed = true, array $data = [], int $uriid = 0): string + public static function convertAttachment(string $text, int $simplehtml = self::INTERNAL, bool $tryoembed = true, array $data = [], int $uriid = 0, int $preview_mode = self::PREVIEW_LARGE): string { DI::profiler()->startRecording('rendering'); $data = $data ?: self::getAttachmentData($text); @@ -689,12 +695,18 @@ class BBCode $return = sprintf('
', $data['type']); } + if ($preview_mode == self::PREVIEW_NO_IMAGE) { + unset($data['image']); + unset($data['preview']); + } + if (!empty($data['title']) && !empty($data['url'])) { + $preview_class = $preview_mode == self::PREVIEW_LARGE ? 'attachment-image' : 'attachment-preview'; if (!empty($data['image']) && empty($data['text']) && ($data['type'] == 'photo')) { - $return .= sprintf('', $data['url'], self::proxyUrl($data['image'], $simplehtml, $uriid), $data['title']); + $return .= sprintf('', $data['url'], self::proxyUrl($data['image'], $simplehtml, $uriid), $data['title']); } else { if (!empty($data['image'])) { - $return .= sprintf('
', $data['url'], self::proxyUrl($data['image'], $simplehtml, $uriid), $data['title']); + $return .= sprintf('
', $data['url'], self::proxyUrl($data['image'], $simplehtml, $uriid), $data['title']); } elseif (!empty($data['preview'])) { $return .= sprintf('
', $data['url'], self::proxyUrl($data['preview'], $simplehtml, $uriid), $data['title']); } diff --git a/src/Model/Item.php b/src/Model/Item.php index 8026d567cb..625567a3ca 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3004,7 +3004,7 @@ class Item $item['hashtags'] = $tags['hashtags']; $item['mentions'] = $tags['mentions']; - $body = $item['body'] ?? ''; + $body = $item['body'] = Post\Media::removeFromEndOfBody($item['body'] ?? ''); $fields = ['uri-id', 'uri', 'body', 'title', 'author-name', 'author-link', 'author-avatar', 'guid', 'created', 'plink', 'network', 'has-media', 'quote-uri-id', 'post-type']; @@ -3402,7 +3402,10 @@ class Item } // @todo Use a template - $rendered = BBCode::convertAttachment('', BBCode::INTERNAL, false, $data, $uriid); + $preview_mode = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'preview_mode', BBCode::PREVIEW_LARGE); + if ($preview_mode != BBCode::PREVIEW_NONE) { + $rendered = BBCode::convertAttachment('', BBCode::INTERNAL, false, $data, $uriid, $preview_mode); + } } elseif (!self::containsLink($content, $data['url'], Post\Media::HTML)) { $rendered = Renderer::replaceMacros(Renderer::getMarkupTemplate('content/link.tpl'), [ '$url' => $data['url'], diff --git a/src/Model/Post/Media.php b/src/Model/Post/Media.php index 62590594be..d3d26a8511 100644 --- a/src/Model/Post/Media.php +++ b/src/Model/Post/Media.php @@ -446,13 +446,14 @@ class Media * @param string $body * @return string Body without media links */ - public static function insertFromBody(int $uriid, string $body): string + public static function insertFromBody(int $uriid, string $body, bool $endmatch = false): string { + $endmatchpattern = $endmatch ? '\z' : ''; // Simplify image codes - $unshared_body = $body = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $body); + $unshared_body = $body = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]$endmatchpattern/ism", '[img]$3[/img]', $body); $attachments = []; - if (preg_match_all("#\[url=([^\]]+?)\]\s*\[img=([^\[\]]*)\]([^\[\]]*)\[\/img\]\s*\[/url\]#ism", $body, $pictures, PREG_SET_ORDER)) { + if (preg_match_all("#\[url=([^\]]+?)\]\s*\[img=([^\[\]]*)\]([^\[\]]*)\[\/img\]\s*\[/url\]$endmatchpattern#ism", $body, $pictures, PREG_SET_ORDER)) { foreach ($pictures as $picture) { if (!self::isPictureLink($picture[1], $picture[2])) { continue; @@ -464,14 +465,14 @@ class Media } } - if (preg_match_all("/\[img=([^\[\]]*)\]([^\[\]]*)\[\/img\]/Usi", $body, $pictures, PREG_SET_ORDER)) { + if (preg_match_all("/\[img=([^\[\]]*)\]([^\[\]]*)\[\/img\]$endmatchpattern/Usi", $body, $pictures, PREG_SET_ORDER)) { foreach ($pictures as $picture) { $body = str_replace($picture[0], '', $body); $attachments[$picture[1]] = ['uri-id' => $uriid, 'type' => self::IMAGE, 'url' => $picture[1], 'description' => $picture[2]]; } } - if (preg_match_all("#\[url=([^\]]+?)\]\s*\[img\]([^\[]+?)\[/img\]\s*\[/url\]#ism", $body, $pictures, PREG_SET_ORDER)) { + if (preg_match_all("#\[url=([^\]]+?)\]\s*\[img\]([^\[]+?)\[/img\]\s*\[/url\]$endmatchpattern#ism", $body, $pictures, PREG_SET_ORDER)) { foreach ($pictures as $picture) { if (!self::isPictureLink($picture[1], $picture[2])) { continue; @@ -483,41 +484,58 @@ class Media } } - if (preg_match_all("/\[img\]([^\[\]]*)\[\/img\]/ism", $body, $pictures, PREG_SET_ORDER)) { + if (preg_match_all("/\[img\]([^\[\]]*)\[\/img\]$endmatchpattern/ism", $body, $pictures, PREG_SET_ORDER)) { foreach ($pictures as $picture) { $body = str_replace($picture[0], '', $body); $attachments[$picture[1]] = ['uri-id' => $uriid, 'type' => self::IMAGE, 'url' => $picture[1]]; } } - if (preg_match_all("/\[audio\]([^\[\]]*)\[\/audio\]/ism", $body, $audios, PREG_SET_ORDER)) { + if (preg_match_all("/\[audio\]([^\[\]]*)\[\/audio\]$endmatchpattern/ism", $body, $audios, PREG_SET_ORDER)) { foreach ($audios as $audio) { $body = str_replace($audio[0], '', $body); $attachments[$audio[1]] = ['uri-id' => $uriid, 'type' => self::AUDIO, 'url' => $audio[1]]; } } - if (preg_match_all("/\[video\]([^\[\]]*)\[\/video\]/ism", $body, $videos, PREG_SET_ORDER)) { + if (preg_match_all("/\[video\]([^\[\]]*)\[\/video\]$endmatchpattern/ism", $body, $videos, PREG_SET_ORDER)) { foreach ($videos as $video) { $body = str_replace($video[0], '', $body); $attachments[$video[1]] = ['uri-id' => $uriid, 'type' => self::VIDEO, 'url' => $video[1]]; } } - foreach ($attachments as $attachment) { - if (Post\Link::exists($uriid, $attachment['preview'] ?? $attachment['url'])) { - continue; - } + if ($uriid != 0) { + foreach ($attachments as $attachment) { + if (Post\Link::exists($uriid, $attachment['preview'] ?? $attachment['url'])) { + continue; + } - // Only store attachments that are part of the unshared body - if (Item::containsLink($unshared_body, $attachment['preview'] ?? $attachment['url'], $attachment['type'])) { - self::insert($attachment); + // Only store attachments that are part of the unshared body + if (Item::containsLink($unshared_body, $attachment['preview'] ?? $attachment['url'], $attachment['type'])) { + self::insert($attachment); + } } } return trim($body); } + /** + * Remove media that is at the end of the body + * + * @param string $body + * @return string + */ + public static function removeFromEndOfBody(string $body): string + { + do { + $prebody = $body; + $body = self::insertFromBody(0, $body, true); + } while ($prebody != $body); + return $body; + } + /** * Add media links from a relevant url in the body * diff --git a/src/Module/Settings/Display.php b/src/Module/Settings/Display.php index 11c3f51393..1484790d9a 100644 --- a/src/Module/Settings/Display.php +++ b/src/Module/Settings/Display.php @@ -21,7 +21,9 @@ namespace Friendica\Module\Settings; +use Friendica\Content\Text\BBCode; use Friendica\Core\Hook; +use Friendica\Core\Logger; use Friendica\Core\Renderer; use Friendica\Core\Theme; use Friendica\Database\DBA; @@ -55,6 +57,7 @@ class Display extends BaseSettings $enable_dislike = !empty($_POST['enable_dislike']) ? intval($_POST['enable_dislike']) : 0; $display_resharer = !empty($_POST['display_resharer']) ? intval($_POST['display_resharer']) : 0; $stay_local = !empty($_POST['stay_local']) ? intval($_POST['stay_local']) : 0; + $preview_mode = !empty($_POST['preview_mode']) ? intval($_POST['preview_mode']) : 0; $browser_update = !empty($_POST['browser_update']) ? intval($_POST['browser_update']) : 0; if ($browser_update != -1) { $browser_update = $browser_update * 1000; @@ -91,6 +94,7 @@ class Display extends BaseSettings DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'system', 'display_resharer' , $display_resharer); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'system', 'stay_local' , $stay_local); DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'system', 'first_day_of_week' , $first_day_of_week); + DI::pConfig()->set(DI::userSession()->getLocalUserId(), 'system', 'preview_mode' , $preview_mode); if (in_array($theme, Theme::getAllowedList())) { if ($theme == $user['theme']) { @@ -175,7 +179,7 @@ class Display extends BaseSettings $enable_dislike = !DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'hide_dislike', 0); $display_resharer = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'display_resharer', 0); $stay_local = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'stay_local', 0); - + $preview_mode = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'preview_mode', BBCode::PREVIEW_LARGE); $first_day_of_week = DI::pConfig()->get(DI::userSession()->getLocalUserId(), 'system', 'first_day_of_week', 0); $weekdays = [ @@ -188,6 +192,13 @@ class Display extends BaseSettings 6 => DI::l10n()->t("Saturday") ]; + $preview_modes = [ + BBCode::PREVIEW_NONE => DI::l10n()->t('No preview'), + BBCode::PREVIEW_NO_IMAGE => DI::l10n()->t('No image'), + BBCode::PREVIEW_SMALL => DI::l10n()->t('Small Image'), + BBCode::PREVIEW_LARGE => DI::l10n()->t('Large Image'), + ]; + $theme_config = ''; if ($themeconfigfile = Theme::getConfigFile($theme_selected)) { require_once $themeconfigfile; @@ -222,6 +233,7 @@ class Display extends BaseSettings '$enable_dislike' => ['enable_dislike' , DI::l10n()->t('Display the Dislike feature'), $enable_dislike, DI::l10n()->t('Display the Dislike button and dislike reactions on posts and comments.')], '$display_resharer' => ['display_resharer' , DI::l10n()->t('Display the resharer'), $display_resharer, DI::l10n()->t('Display the first resharer as icon and text on a reshared item.')], '$stay_local' => ['stay_local' , DI::l10n()->t('Stay local'), $stay_local, DI::l10n()->t("Don't go to a remote system when following a contact link.")], + '$preview_mode' => ['preview_mode' , DI::l10n()->t('Link preview mode'), $preview_mode, 'Appearance of the link preview that is added to each post with a link.', $preview_modes, false], '$first_day_of_week' => ['first_day_of_week', DI::l10n()->t('Beginning of week:'), $first_day_of_week, '', $weekdays, false], ]); diff --git a/view/templates/settings/display.tpl b/view/templates/settings/display.tpl index 4e065edf00..7e3efc9201 100644 --- a/view/templates/settings/display.tpl +++ b/view/templates/settings/display.tpl @@ -20,6 +20,7 @@ {{include file="field_checkbox.tpl" field=$enable_dislike}} {{include file="field_checkbox.tpl" field=$display_resharer}} {{include file="field_checkbox.tpl" field=$stay_local}} + {{include file="field_select.tpl" field=$preview_mode}}

{{$calendar_title}}

{{include file="field_select.tpl" field=$first_day_of_week}} diff --git a/view/theme/frio/templates/settings/display.tpl b/view/theme/frio/templates/settings/display.tpl index 004f1884e2..530a40a969 100644 --- a/view/theme/frio/templates/settings/display.tpl +++ b/view/theme/frio/templates/settings/display.tpl @@ -67,6 +67,7 @@ {{include file="field_checkbox.tpl" field=$enable_dislike}} {{include file="field_checkbox.tpl" field=$display_resharer}} {{include file="field_checkbox.tpl" field=$stay_local}} + {{include file="field_select.tpl" field=$preview_mode}}