Merge pull request #10177 from annando/media-preview
Preview for Videos and images / Video resolution selection
This commit is contained in:
commit
e41283faff
9 changed files with 62 additions and 35 deletions
|
@ -35,13 +35,13 @@ use Friendica\Core\Worker;
|
||||||
use Friendica\Database\DBA;
|
use Friendica\Database\DBA;
|
||||||
use Friendica\DI;
|
use Friendica\DI;
|
||||||
use Friendica\Model\Post;
|
use Friendica\Model\Post;
|
||||||
use Friendica\Model\Post\Media;
|
|
||||||
use Friendica\Protocol\Activity;
|
use Friendica\Protocol\Activity;
|
||||||
use Friendica\Protocol\ActivityPub;
|
use Friendica\Protocol\ActivityPub;
|
||||||
use Friendica\Protocol\Diaspora;
|
use Friendica\Protocol\Diaspora;
|
||||||
use Friendica\Util\DateTimeFormat;
|
use Friendica\Util\DateTimeFormat;
|
||||||
use Friendica\Util\Map;
|
use Friendica\Util\Map;
|
||||||
use Friendica\Util\Network;
|
use Friendica\Util\Network;
|
||||||
|
use Friendica\Util\Proxy;
|
||||||
use Friendica\Util\Strings;
|
use Friendica\Util\Strings;
|
||||||
use Friendica\Worker\Delivery;
|
use Friendica\Worker\Delivery;
|
||||||
use LanguageDetection\Language;
|
use LanguageDetection\Language;
|
||||||
|
@ -2667,7 +2667,7 @@ class Item
|
||||||
$shared_item = Post::selectFirst(['uri-id', 'plink'], ['guid' => $shared['guid']]);
|
$shared_item = Post::selectFirst(['uri-id', 'plink'], ['guid' => $shared['guid']]);
|
||||||
$shared_uri_id = $shared_item['uri-id'] ?? 0;
|
$shared_uri_id = $shared_item['uri-id'] ?? 0;
|
||||||
$shared_plink = $shared_item['plink'] ?? '';
|
$shared_plink = $shared_item['plink'] ?? '';
|
||||||
$attachments = Post\Media::splitAttachments($shared_uri_id);
|
$attachments = Post\Media::splitAttachments($shared_uri_id, $shared['guid']);
|
||||||
$s = self::addVisualAttachments($attachments, $item, $s, true);
|
$s = self::addVisualAttachments($attachments, $item, $s, true);
|
||||||
$s = self::addLinkAttachment($attachments, $item, $s, true, '');
|
$s = self::addLinkAttachment($attachments, $item, $s, true, '');
|
||||||
$s = self::addNonVisualAttachments($attachments, $item, $s, true);
|
$s = self::addNonVisualAttachments($attachments, $item, $s, true);
|
||||||
|
@ -2676,7 +2676,7 @@ class Item
|
||||||
$shared_plink = '';
|
$shared_plink = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
$attachments = Post\Media::splitAttachments($item['uri-id']);
|
$attachments = Post\Media::splitAttachments($item['uri-id'], $item['guid']);
|
||||||
$s = self::addVisualAttachments($attachments, $item, $s, false);
|
$s = self::addVisualAttachments($attachments, $item, $s, false);
|
||||||
$s = self::addLinkAttachment($attachments, $item, $s, false, $shared_plink);
|
$s = self::addLinkAttachment($attachments, $item, $s, false, $shared_plink);
|
||||||
$s = self::addNonVisualAttachments($attachments, $item, $s, false);
|
$s = self::addNonVisualAttachments($attachments, $item, $s, false);
|
||||||
|
@ -2747,13 +2747,21 @@ class Item
|
||||||
'network' => $item['author-network'], 'url' => $item['author-link']];
|
'network' => $item['author-network'], 'url' => $item['author-link']];
|
||||||
$the_url = Contact::magicLinkByContact($author, $attachment['url']);
|
$the_url = Contact::magicLinkByContact($author, $attachment['url']);
|
||||||
|
|
||||||
|
if (!empty($attachment['preview'])) {
|
||||||
|
$preview_url = Proxy::proxifyUrl(Contact::magicLinkByContact($author, $attachment['preview']));
|
||||||
|
} else {
|
||||||
|
$preview_url = '';
|
||||||
|
}
|
||||||
|
|
||||||
if (($attachment['filetype'] == 'video')) {
|
if (($attachment['filetype'] == 'video')) {
|
||||||
/// @todo Move the template to /content as well
|
/// @todo Move the template to /content as well
|
||||||
$media = Renderer::replaceMacros(Renderer::getMarkupTemplate('video_top.tpl'), [
|
$media = Renderer::replaceMacros(Renderer::getMarkupTemplate('video_top.tpl'), [
|
||||||
'$video' => [
|
'$video' => [
|
||||||
'id' => $item['author-id'],
|
'id' => $attachment['id'],
|
||||||
'src' => $the_url,
|
'src' => $the_url,
|
||||||
'mime' => $attachment['mimetype'],
|
'name' => $attachment['name'] ?: $attachment['url'],
|
||||||
|
'preview' => $preview_url,
|
||||||
|
'mime' => $attachment['mimetype'],
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
if ($item['post-type'] == Item::PT_VIDEO) {
|
if ($item['post-type'] == Item::PT_VIDEO) {
|
||||||
|
@ -2764,8 +2772,9 @@ class Item
|
||||||
} elseif ($attachment['filetype'] == 'audio') {
|
} elseif ($attachment['filetype'] == 'audio') {
|
||||||
$media = Renderer::replaceMacros(Renderer::getMarkupTemplate('content/audio.tpl'), [
|
$media = Renderer::replaceMacros(Renderer::getMarkupTemplate('content/audio.tpl'), [
|
||||||
'$audio' => [
|
'$audio' => [
|
||||||
'id' => $item['author-id'],
|
'id' => $attachment['id'],
|
||||||
'src' => $the_url,
|
'src' => $the_url,
|
||||||
|
'name' => $attachment['name'] ?: $attachment['url'],
|
||||||
'mime' => $attachment['mimetype'],
|
'mime' => $attachment['mimetype'],
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
@ -2775,9 +2784,13 @@ class Item
|
||||||
$trailing .= $media;
|
$trailing .= $media;
|
||||||
}
|
}
|
||||||
} elseif ($attachment['filetype'] == 'image') {
|
} elseif ($attachment['filetype'] == 'image') {
|
||||||
|
if (empty($preview_url) && (max($attachment['width'], $attachment['height']) > 600)) {
|
||||||
|
$preview_url = Proxy::proxifyUrl($the_url, false, ($attachment['width'] > $attachment['height']) ? Proxy::SIZE_MEDIUM : Proxy::SIZE_LARGE);
|
||||||
|
}
|
||||||
$media = Renderer::replaceMacros(Renderer::getMarkupTemplate('content/image.tpl'), [
|
$media = Renderer::replaceMacros(Renderer::getMarkupTemplate('content/image.tpl'), [
|
||||||
'$image' => [
|
'$image' => [
|
||||||
'src' => $the_url,
|
'src' => Proxy::proxifyUrl($the_url),
|
||||||
|
'preview' => $preview_url,
|
||||||
'attachment' => $attachment,
|
'attachment' => $attachment,
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -448,9 +448,10 @@ class Media
|
||||||
* Split the attachment media in the three segments "visual", "link" and "additional"
|
* Split the attachment media in the three segments "visual", "link" and "additional"
|
||||||
*
|
*
|
||||||
* @param int $uri_id
|
* @param int $uri_id
|
||||||
|
* @param string $guid
|
||||||
* @return array attachments
|
* @return array attachments
|
||||||
*/
|
*/
|
||||||
public static function splitAttachments(int $uri_id)
|
public static function splitAttachments(int $uri_id, string $guid = '')
|
||||||
{
|
{
|
||||||
$attachments = ['visual' => [], 'link' => [], 'additional' => []];
|
$attachments = ['visual' => [], 'link' => [], 'additional' => []];
|
||||||
|
|
||||||
|
@ -459,6 +460,9 @@ class Media
|
||||||
return $attachments;
|
return $attachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$height = 0;
|
||||||
|
$selected = '';
|
||||||
|
|
||||||
foreach ($media as $medium) {
|
foreach ($media as $medium) {
|
||||||
$type = explode('/', current(explode(';', $medium['mimetype'])));
|
$type = explode('/', current(explode(';', $medium['mimetype'])));
|
||||||
if (count($type) < 2) {
|
if (count($type) < 2) {
|
||||||
|
@ -478,11 +482,31 @@ class Media
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_array($medium['type'], [self::AUDIO, self::VIDEO, self::IMAGE]) ||
|
if (in_array($medium['type'], [self::AUDIO, self::IMAGE]) ||
|
||||||
in_array($filetype, ['audio', 'video', 'image'])) {
|
in_array($filetype, ['audio', 'image'])) {
|
||||||
|
$attachments['visual'][] = $medium;
|
||||||
|
} elseif (($medium['type'] == self::VIDEO) || ($filetype == 'video')) {
|
||||||
|
if (strpos($medium['url'], $guid) !== false) {
|
||||||
|
// Peertube videos are delivered in many different resolutions. We pick a moderate one.
|
||||||
|
// By checking against the GUID we also ensure to only work this way on Peertube posts.
|
||||||
|
// This wouldn't be executed when someone for example on Mastodon was sharing multiple videos in a single post.
|
||||||
|
if (empty($height) || ($height > $medium['height']) && ($medium['height'] >= 480)) {
|
||||||
|
$height = $medium['height'];
|
||||||
|
$selected = $medium['url'];
|
||||||
|
}
|
||||||
|
$video[$medium['url']] = $medium;
|
||||||
|
} else {
|
||||||
$attachments['visual'][] = $medium;
|
$attachments['visual'][] = $medium;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$attachments['additional'][] = $medium;
|
$attachments['additional'][] = $medium;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($selected)) {
|
||||||
|
$attachments['visual'][] = $video[$selected];
|
||||||
|
unset($video[$selected]);
|
||||||
|
foreach ($video as $element) {
|
||||||
|
$attachments['additional'][] = $element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return $attachments;
|
return $attachments;
|
||||||
|
|
|
@ -1268,14 +1268,6 @@ class Receiver
|
||||||
} elseif ($filetype == 'video') {
|
} elseif ($filetype == 'video') {
|
||||||
$height = (int)JsonLD::fetchElement($url, 'as:height', '@value');
|
$height = (int)JsonLD::fetchElement($url, 'as:height', '@value');
|
||||||
$size = (int)JsonLD::fetchElement($url, 'pt:size', '@value');
|
$size = (int)JsonLD::fetchElement($url, 'pt:size', '@value');
|
||||||
|
|
||||||
// We save bandwidth by using a moderate height (alt least 480 pixel height)
|
|
||||||
// Peertube normally uses these heights: 240, 360, 480, 720, 1080
|
|
||||||
if (!empty($attachments[$filetype]['height']) &&
|
|
||||||
($height > $attachments[$filetype]['height']) && ($attachments[$filetype]['height'] >= 480)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$attachments[$filetype] = ['type' => $mediatype, 'url' => $href, 'height' => $height, 'size' => $size];
|
$attachments[$filetype] = ['type' => $mediatype, 'url' => $href, 'height' => $height, 'size' => $size];
|
||||||
} elseif (in_array($mediatype, ['application/x-bittorrent', 'application/x-bittorrent;x-scheme-handler/magnet'])) {
|
} elseif (in_array($mediatype, ['application/x-bittorrent', 'application/x-bittorrent;x-scheme-handler/magnet'])) {
|
||||||
$height = (int)JsonLD::fetchElement($url, 'as:height', '@value');
|
$height = (int)JsonLD::fetchElement($url, 'as:height', '@value');
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<audio src="{{$audio.src}}" controls>
|
<audio src="{{$audio.src}}" controls>
|
||||||
<a href="{{$audio.src}}">{{$audio.src}}</a>
|
<a href="{{$audio.src}}">{{$audio.name}}</a>
|
||||||
</audio>
|
</audio>
|
||||||
<br>
|
<br>
|
||||||
|
|
|
@ -1,2 +1,6 @@
|
||||||
|
{{if $image.preview}}
|
||||||
|
<a href="{{$image.attachment.url}}"><img src="{{$image.preview}}" alt="{{$image.attachment.description}}" title="{{$image.attachment.description}}"></a>
|
||||||
|
{{else}}
|
||||||
<img src="{{$image.src}}" alt="{{$image.attachment.description}}" title="{{$image.attachment.description}}">
|
<img src="{{$image.src}}" alt="{{$image.attachment.description}}" title="{{$image.attachment.description}}">
|
||||||
|
{{/if}}
|
||||||
<br>
|
<br>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="video-top-wrapper lframe" id="video-top-wrapper-{{$video.id}}">
|
<div class="video-top-wrapper lframe" id="video-top-wrapper-{{$video.id}}">
|
||||||
{{* set preloading to none to lessen the load on the server *}}
|
{{* set preloading to none to lessen the load on the server *}}
|
||||||
<video controls preload="none" data-setup="" width="100%" height="auto">
|
<video src="{{$video.src}}" controls {{if $video.preview}}preload="none" poster="{{$video.preview}}" {else}preload="metadata" {{/if}}width="100%" height="auto">
|
||||||
<source src="{{$video.src}}" type="{{$video.mime}}" />
|
<a href="{{$video.src}}">{{$video.name}}</a>
|
||||||
</video>
|
</video>
|
||||||
|
|
||||||
{{if $delete_url }}
|
{{if $delete_url }}
|
||||||
|
|
|
@ -1988,8 +1988,7 @@ code > .hl-main {
|
||||||
}
|
}
|
||||||
/* Like/Comment/etc buttons */
|
/* Like/Comment/etc buttons */
|
||||||
.wall-item-container .wall-item-links,
|
.wall-item-container .wall-item-links,
|
||||||
.wall-item-container .wall-item-actions button,
|
.wall-item-container .wall-item-actions button > a {
|
||||||
.wall-item-container .body-attach > a {
|
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
|
|
||||||
-webkit-transition: all 0.25s ease-in-out;
|
-webkit-transition: all 0.25s ease-in-out;
|
||||||
|
@ -1999,8 +1998,7 @@ code > .hl-main {
|
||||||
transition: all 0.25s ease-in-out;
|
transition: all 0.25s ease-in-out;
|
||||||
}
|
}
|
||||||
.wall-item-container:hover .wall-item-links,
|
.wall-item-container:hover .wall-item-links,
|
||||||
.wall-item-container:hover .wall-item-actions button,
|
.wall-item-container:hover .wall-item-actions button > a {
|
||||||
.wall-item-container:hover .body-attach > a {
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
|
||||||
-webkit-transition: all 0.25s ease-in-out;
|
-webkit-transition: all 0.25s ease-in-out;
|
||||||
|
|
|
@ -261,8 +261,7 @@ input[type="submit"],
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.wall-item-container .wall-item-links,
|
.wall-item-container .wall-item-links,
|
||||||
.wall-item-container .wall-item-actions button,
|
.wall-item-container .wall-item-actions button > a {
|
||||||
.wall-item-container .body-attach > a {
|
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
-webkit-transition: all 0.25s ease-in-out;
|
-webkit-transition: all 0.25s ease-in-out;
|
||||||
-moz-transition: all 0.25s ease-in-out;
|
-moz-transition: all 0.25s ease-in-out;
|
||||||
|
@ -271,8 +270,7 @@ input[type="submit"],
|
||||||
transition: all 0.25s ease-in-out;
|
transition: all 0.25s ease-in-out;
|
||||||
}
|
}
|
||||||
.wall-item-container:hover .wall-item-links,
|
.wall-item-container:hover .wall-item-links,
|
||||||
.wall-item-container:hover .wall-item-actions button,
|
.wall-item-container:hover .wall-item-actions button > a {
|
||||||
.wall-item-container:hover .body-attach > a {
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
-webkit-transition: all 0.25s ease-in-out;
|
-webkit-transition: all 0.25s ease-in-out;
|
||||||
-moz-transition: all 0.25s ease-in-out;
|
-moz-transition: all 0.25s ease-in-out;
|
||||||
|
|
|
@ -250,8 +250,7 @@ input[type="submit"],
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.wall-item-container .wall-item-links,
|
.wall-item-container .wall-item-links,
|
||||||
.wall-item-container .wall-item-actions button,
|
.wall-item-container .wall-item-actions button > a {
|
||||||
.wall-item-container .body-attach > a {
|
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
-webkit-transition: all 0.25s ease-in-out;
|
-webkit-transition: all 0.25s ease-in-out;
|
||||||
-moz-transition: all 0.25s ease-in-out;
|
-moz-transition: all 0.25s ease-in-out;
|
||||||
|
@ -260,8 +259,7 @@ input[type="submit"],
|
||||||
transition: all 0.25s ease-in-out;
|
transition: all 0.25s ease-in-out;
|
||||||
}
|
}
|
||||||
.wall-item-container:hover .wall-item-links,
|
.wall-item-container:hover .wall-item-links,
|
||||||
.wall-item-container:hover .wall-item-actions button,
|
.wall-item-container:hover .wall-item-actions button > a {
|
||||||
.wall-item-container:hover .body-attach > a {
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
-webkit-transition: all 0.25s ease-in-out;
|
-webkit-transition: all 0.25s ease-in-out;
|
||||||
-moz-transition: all 0.25s ease-in-out;
|
-moz-transition: all 0.25s ease-in-out;
|
||||||
|
|
Loading…
Reference in a new issue