From fdda2e4e0dc0358309f6b119c8f8e536602618fd Mon Sep 17 00:00:00 2001 From: Hannes Mannerheim Date: Wed, 17 Jun 2015 00:44:18 +0200 Subject: [PATCH] no autoplay for animated gifs, better handling of youtube and webm videos also solves @moshpirit's issue in #190, but when there's a mix of local images and videos gnusocial messes up the order... --- QvitterPlugin.php | 43 +++++++++++++---- css/qvitter.css | 39 +++++++++++++-- js/dom-functions.js | 112 +++++++++++++++++++++++++++++--------------- js/qvitter.js | 59 ++++++++++++++++++++--- 4 files changed, 195 insertions(+), 58 deletions(-) diff --git a/QvitterPlugin.php b/QvitterPlugin.php index 44d047e..053e38f 100644 --- a/QvitterPlugin.php +++ b/QvitterPlugin.php @@ -422,18 +422,42 @@ class QvitterPlugin extends Plugin { try { $enclosure_o = $attachment->getEnclosure(); $thumb = $attachment->getThumbnail(); + $attachment_url_to_id[$enclosure_o->url]['id'] = $attachment->id; $attachment_url_to_id[$enclosure_o->url]['thumb_url'] = $thumb->getUrl(); $attachment_url_to_id[$enclosure_o->url]['width'] = $attachment->width; $attachment_url_to_id[$enclosure_o->url]['height'] = $attachment->height; + + // animated gif? + if($attachment->mimetype == 'image/gif') { + $image = ImageFile::fromFileObject($attachment); + if($image->animated == 1) { + $attachment_url_to_id[$enclosure_o->url]['animated'] = true; + } + else { + $attachment_url_to_id[$enclosure_o->url]['animated'] = false; + } + } + } catch (ServerException $e) { $thumb = File_thumbnail::getKV('file_id', $attachment->id); if ($thumb instanceof File_thumbnail) { $attachment_url_to_id[$enclosure_o->url]['id'] = $attachment->id; $attachment_url_to_id[$enclosure_o->url]['thumb_url'] = $thumb->getUrl(); $attachment_url_to_id[$enclosure_o->url]['width'] = $attachment->width; - $attachment_url_to_id[$enclosure_o->url]['height'] = $attachment->height; - } + $attachment_url_to_id[$enclosure_o->url]['height'] = $attachment->height; + + // animated gif? + if($attachment->mimetype == 'image/gif') { + $image = ImageFile::fromFileObject($attachment); + if($image->animated == 1) { + $attachment_url_to_id[$enclosure_o->url]['animated'] = true; + } + else { + $attachment_url_to_id[$enclosure_o->url]['animated'] = false; + } + } + } } } } @@ -445,13 +469,11 @@ class QvitterPlugin extends Plugin { if (!empty($attachment_url_to_id[$attachment['url']])) { $attachment['id'] = $attachment_url_to_id[$attachment['url']]['id']; $attachment['width'] = $attachment_url_to_id[$attachment['url']]['width']; - $attachment['height'] = $attachment_url_to_id[$attachment['url']]['height']; - - // if the attachment is other than image, and we have a thumb (e.g. videos), - // we include the default thumbnail url - if(substr($attachment['mimetype'],0,5) != 'image') { - $attachment['thumb_url'] = $attachment_url_to_id[$attachment['url']]['thumb_url']; - } + $attachment['height'] = $attachment_url_to_id[$attachment['url']]['height']; + $attachment['thumb_url'] = $attachment_url_to_id[$attachment['url']]['thumb_url']; + if(isset($attachment_url_to_id[$attachment['url']]['animated'])) { + $attachment['animated'] = $attachment_url_to_id[$attachment['url']]['animated']; + } } } } @@ -554,7 +576,6 @@ class QvitterPlugin extends Plugin { return true; } - /** @@ -591,6 +612,7 @@ class QvitterPlugin extends Plugin { * @return boolean hook flag */ function onStartNoticeDistribute($notice) { + assert($notice->id > 0); // since we removed tests below // don't add notifications for activity type notices @@ -658,6 +680,7 @@ class QvitterPlugin extends Plugin { return true; } + /** * Delete any notifications tied to deleted notices and un-repeats diff --git a/css/qvitter.css b/css/qvitter.css index 67865aa..62834b7 100644 --- a/css/qvitter.css +++ b/css/qvitter.css @@ -1693,7 +1693,13 @@ body.rtl .queet.rtl .expanded-content { background-size:100% auto; } -.queet .thumb-container[href*="://www.youtube.com"]:before { +.queet .queet-thumbs.thumb-num-1 .thumb-container.youtube { + height:250px; + } + +.stream-item:not(.expanded) .queet .queet-thumbs.thumb-num-1 .thumb-container.play-button:before, +.queet .queet-thumbs:not(.thumb-num-1) .thumb-container.play-button:before, +.modal-content .queet .thumb-container.play-button:before { display:block; position:absolute; width:100%; @@ -1706,12 +1712,12 @@ body.rtl .queet.rtl .expanded-content { font-size:100px; color:rgba(255,255,255,0.65); } -.queet .thumb-container[href*="://www.youtube.com"] img { +.queet .thumb-container.play-button img { z-index:2; position:relative; } -.queet .queet-thumbs .thumb-container.no-cover .attachment-thumb { +.queet .queet-thumbs.thumb-num-1 .thumb-container.no-cover .attachment-thumb { min-height:0; } .queet .thumb-container:before { @@ -1864,6 +1870,14 @@ body.rtl .queet.rtl .expanded-content { max-height: 125px; min-height: 125px; } +.queet .queet-thumbs.thumb-num-6 .thumb-container.play-button:before, +.queet .queet-thumbs.thumb-num-7 .thumb-container.play-button:before, +.queet .queet-thumbs.thumb-num-8 .thumb-container.play-button:before, +.queet .queet-thumbs.thumb-num-9 .thumb-container.play-button:before, +.queet .queet-thumbs.thumb-num-10 .thumb-container.play-button:before{ + line-height: 125px; + font-size:70px; + } .queet .queet-thumbs.thumb-num-11 .thumb-container, .queet .queet-thumbs.thumb-num-12 .thumb-container, .queet .queet-thumbs.thumb-num-13 .thumb-container, @@ -1878,6 +1892,15 @@ body.rtl .queet.rtl .expanded-content { .queet .queet-thumbs.thumb-num-more-than-fifteen .attachment-thumb { max-height: 83px; min-height: 83px; + } +.queet .queet-thumbs.thumb-num-11 .thumb-container.play-button:before, +.queet .queet-thumbs.thumb-num-12 .thumb-container.play-button:before, +.queet .queet-thumbs.thumb-num-13 .thumb-container.play-button:before, +.queet .queet-thumbs.thumb-num-14 .thumb-container.play-button:before, +.queet .queet-thumbs.thumb-num-15 .thumb-container.play-button:before, +.queet .queet-thumbs.thumb-num-more-than-fifteen .thumb-container.play-button:before { + line-height: 83px; + font-size:50px; } .stream-item.collapsing > .queet .thumb-container { @@ -4045,6 +4068,14 @@ body.rtl .modal-footer button { margin: 0 auto; min-height: 0; } +#queet-thumb-popup .modal-body .thumb-container.youtube iframe { + position:absolute; + z-index:2; + } +#queet-thumb-popup .modal-body .thumb-container.youtube { + background-image:none !important; + z-index:1; + } #queet-thumb-popup .modal-body .thumb-container[href$=".svg"], #queet-thumb-popup .modal-body .thumb-container[href$=".png"] { background-color:#fff; @@ -4093,7 +4124,7 @@ body.rtl .modal-footer button { } #queet-thumb-popup .prev-thumb.disabled, #queet-thumb-popup .next-thumb.disabled { - color:#aaa; + color:rgba(255,255,255,0.2); cursor:default; } #queet-thumb-popup .prev-thumb:not(.disabled):hover:before, diff --git a/js/dom-functions.js b/js/dom-functions.js index 90c14f8..841b9ca 100644 --- a/js/dom-functions.js +++ b/js/dom-functions.js @@ -1001,6 +1001,17 @@ function expand_queet(q,doScrolling) { // remove some things right away q.find('.inline-reply-caret').remove(); + // "unplay" gif image on collapse if there's only one attachment (switch to thumb) + var gifToUnPlay = q.children('.queet').find('.queet-thumbs.thumb-num-1').children('.thumb-container.play-button').children('.attachment-thumb[data-mime-type="image/gif"]'); + if(gifToUnPlay.length > 0) { + gifToUnPlay.attr('src',gifToUnPlay.attr('data-thumb-url')); + gifToUnPlay.parent('.thumb-container').css('background-image','url(\'' + gifToUnPlay.attr('data-thumb-url') + '\')'); + } + + // show thumbs (if hidden) and remove any iframe video immediately + q.children('.queet').find('.queet-thumbs').removeClass('hide-thumbs'); + q.children('.queet').find('iframe').remove(); + q.addClass('collapsing'); if(q.hasClass('conversation')) { q.removeClass('expanded'); @@ -1097,7 +1108,7 @@ function expand_queet(q,doScrolling) { } }); } - + // add expanded container var longdate = parseTwitterLongDate(q.find('.created-at').attr('data-created-at')); var qurl = q.find('.created-at').find('a').attr('href'); @@ -1106,57 +1117,62 @@ function expand_queet(q,doScrolling) { // show expanded content q.find('.stream-item-footer').before('
'); - - // maybe show images or videos, look for them in both the text and in the thumbnail container - $.each(q.children('.queet').find('.queet-text, .attachments').find('a'), function() { - - var attachment_mimetype = $(this).find('img').attr('data-mime-type'); - - if(typeof attachment_mimetype == 'undefined') { - attachment_mimetype = ''; + // "play" gif image on expand if there's only one attachment (switch to full gif from thumb) + var gifToPlay = q.children('.queet').find('.queet-thumbs.thumb-num-1').children('.thumb-container.play-button').children('.attachment-thumb[data-mime-type="image/gif"]'); + if(gifToPlay.length > 0) { + gifToPlay.attr('src',gifToPlay.attr('data-full-image-url')); + gifToPlay.parent('.thumb-container').css('background-image','url(\'' + gifToPlay.attr('data-full-image-url') + '\')'); } - var attachment_title = $(this).attr('title'); - - // attachments in the .attachments container don't have a title, their full url is in the href - if(typeof attachment_title == 'undefined') { - attachment_title = $(this).attr('href'); - } + // if there's only one thumb and it's a youtube video, show it inline + if(q.children('.queet').find('.queet-thumbs.thumb-num-1').children('.thumb-container.play-button.youtube').length == 1) { + var youtubeId = q.children('.queet').find('.queet-thumbs.thumb-num-1').children('.thumb-container.play-button.youtube').children('.attachment-thumb').attr('data-full-image-url').replace('http://www.youtube.com/watch?v=','').replace('https://www.youtube.com/watch?v=','').replace('http://youtu.be/','').replace('https://youtu.be/','').substr(0,11); + if(q.children('.queet').find('.expanded-content').children('.media').children('iframe[src="//www.youtube.com/embed/' + youtubeId + '"]').length < 1) { // not if already showed + // hide video thumbnail if it's the only one + if(q.children('.queet').find('.queet-thumbs').children('.thumb-container').length < 2) { + q.children('.queet').find('.queet-thumbs').addClass('hide-thumbs'); + } + // show video + q.children('.queet').find('.expanded-content').prepend('
'); + } + } + + // show certain attachments in expanded content + $.each(q.data('attachments'), function() { + var attachment_mimetype = this.mimetype; + var attachment_title = this.url; + // filename extension var attachment_title_extension = attachment_title.substr((~-attachment_title.lastIndexOf(".") >>> 0) + 2); // attachments in the content link to /attachment/etc url and not direct to image/video, link is in title if(typeof attachment_title != 'undefined') { + + // hack to make remote webm-movies load + if(attachment_title_extension == 'webm') { + attachment_mimetype = 'video/webm'; + } + // videos - if($.inArray(attachment_mimetype, ['video/mp4', 'video/ogg', 'video/quicktime', 'video/webm']) >= 0) { + if($.inArray(attachment_mimetype, ['video/mp4', 'video/ogg', 'video/quicktime', 'video/webm']) >=0) { if(q.children('.queet').find('.expanded-content').children('.media').children('video').children('source[href="' + attachment_title + '"]').length < 1) { // not if already showed // local attachment with a thumbnail - if(typeof $(this).find('img').attr('data-big-thumbnail') != 'undefined') { - var attachment_poster = $(this).find('img').attr('data-big-thumbnail'); + var attachment_poster = ''; + if(typeof this.thumb_url != 'undefined') { + attachment_poster = ' poster="' + this.thumb_url + '"'; } if(q.children('.queet').find('.expanded-content').children('.media').length > 0) { - q.children('.queet').find('.media').last().after('
'); + q.children('.queet').find('.media').last().after('
'); } else { - q.children('.queet').find('.expanded-content').prepend('
'); + q.children('.queet').find('.expanded-content').prepend('
'); } } } - else if(attachment_title.indexOf('youtube.com/watch?v=') > -1 || attachment_title.indexOf('://youtu.be/') > -1) { - var youtubeId = attachment_title.replace('http://www.youtube.com/watch?v=','').replace('https://www.youtube.com/watch?v=','').replace('http://youtu.be/','').replace('https://youtu.be/','').substr(0,11); - if(q.children('.queet').find('.expanded-content').children('.media').children('iframe[src="//www.youtube.com/embed/' + youtubeId + '"]').length < 1) { // not if already showed - // hide video thumbnail if it's the only one - if(q.children('.queet').find('.queet-thumbs').children('.thumb-container').length < 2) { - q.children('.queet').find('.queet-thumbs').addClass('hide-thumbs'); - } - // show video - q.children('.queet').find('.expanded-content').prepend('
'); - } - } else { // other plugins, e.g. gotabulo, can check for other attachment file formats to expand window.currentlyExpanding = { @@ -1209,7 +1225,6 @@ function cleanUpAfterCollapseQueet(q) { q.children('.queet').removeAttr('style'); q.children('.queet').find('.queet-thumbs.thumb-num-1').removeAttr('style'); q.children('.queet').find('.queet-thumbs.thumb-num-1 .thumb-container').css('max-height',''); - q.children('.queet').find('.queet-thumbs').removeClass('hide-thumbs'); } @@ -1932,7 +1947,7 @@ function buildQueetHtml(obj, idInStream, extraClassesThisRun, requeeted_by, isCo var attachmentNum = 0; if(typeof obj.attachments != "undefined") { $.each(obj.attachments, function(){ - if(this.id != null) { + if(this.id != null) { // if there's an id we assume this is a image or video var bigThumbW = 1000; var bigThumbH = 3000; if(bigThumbW > window.siteMaxThumbnailSize) { @@ -1947,19 +1962,39 @@ function buildQueetHtml(obj, idInStream, extraClassesThisRun, requeeted_by, isCo if(this.width/this.height > 2) { noCoverClass=' no-cover'; } - - // if thumb_url is set, we use that - if(typeof this.thumb_url != 'undefined') { - var img_url = this.thumb_url; + + // play button for videos and animated gifs + var playButtonClass = ''; + if(this.url.indexOf('://www.youtube.com') > -1 + || (typeof this.animated != 'undefined' && this.animated === true)) { + var playButtonClass = ' play-button'; } + + // youtube class + var youTubeClass = ''; + if(this.url.indexOf('://www.youtube.com') > -1) { + youTubeClass = ' youtube'; + } + + + // animated gifs always get default small non-animated thumbnail + if(this.animated === true && typeof this.thumb_url != 'undefined') { + var img_url = this.thumb_url; + } + // if no dimensions are set, go with default thumb + else if(this.width === null && this.height === null && typeof this.thumb_url != 'undefined') { + var img_url = this.thumb_url; + } + // large images get large thumbnail else if(this.width > 1000) { var img_url = window.siteAttachmentURLBase + this.id + '/thumbnail?w=' + bigThumbW + '&h=' + bigThumbH; } + // no thumbnails for small images else { var img_url = this.url; } - attachment_html = attachment_html + ''; + attachment_html = attachment_html + ''; attachmentNum++; } else if (this.mimetype == 'image/svg+xml') { @@ -1988,6 +2023,7 @@ function buildQueetHtml(obj, idInStream, extraClassesThisRun, requeeted_by, isCo var queetHtml = '
'); + } + }); + + // navigation buttons var imgNum = parentStreamItem.children('.queet').find('.attachment-thumb').length; if(imgNum > 1) { $queetThumbsClone.find('.queet-thumbs').before('
'); @@ -1478,12 +1500,14 @@ $('body').on('click','.stream-item .queet img.attachment-thumb',function (event) if(parentStreamItem.hasClass('expanded')) { - var calculatedDimensions = calculatePopUpAndImageDimensions($(this).attr('src')); - var $thisImgInQueetThumbsClone = $queetThumbsClone.find('img[src="' + $(this).attr('src') + '"]'); + var calculatedDimensions = calculatePopUpAndImageDimensions($thumbToDisplay.attr('src')); + var $thisImgInQueetThumbsClone = $queetThumbsClone.find('img[src="' + $thumbToDisplay.attr('src') + '"]'); // set dimensions $thisImgInQueetThumbsClone.width(calculatedDimensions.displayImgWidth); $thisImgInQueetThumbsClone.parent('.thumb-container').width(calculatedDimensions.displayImgWidth); + $thisImgInQueetThumbsClone.parent('.thumb-container').children('iframe').attr('width',calculatedDimensions.displayImgWidth); + $thisImgInQueetThumbsClone.parent('.thumb-container').children('iframe').attr('height',calculatedDimensions.displayImgHeight); // open popup popUpAction('queet-thumb-popup', '', '' + $queetThumbsClone.outerHTML() + '', footerHTML, calculatedDimensions.popUpWidth); @@ -1562,11 +1586,22 @@ $('body').on('click','#queet-thumb-popup .attachment-thumb',function (event) { var nextImage = $(this).parent().next().children('.attachment-thumb'); if(nextImage.length>0) { + + // start and stop youtube videos, if any + $.each($(this).parent('.youtube').children('iframe'),function(){ + this.contentWindow.postMessage('{"event":"command","func":"' + 'stopVideo' + '","args":""}', '*'); + }); + $.each(nextImage.parent('.youtube').children('iframe'),function(){ + this.contentWindow.postMessage('{"event":"command","func":"' + 'playVideo' + '","args":""}', '*'); + }); + // set dimensions of next image and the popup var calculatedDimensions = calculatePopUpAndImageDimensions(nextImage.attr('src')); - nextImage.width(calculatedDimensions.displayImgWidth); + nextImage.width(calculatedDimensions.displayImgWidth); nextImage.parent('.thumb-container').width(calculatedDimensions.displayImgWidth); - $('#queet-thumb-popup .modal-draggable').width(calculatedDimensions.popUpWidth); + nextImage.parent('.thumb-container').children('iframe').attr('width',calculatedDimensions.displayImgWidth); + nextImage.parent('.thumb-container').children('iframe').attr('height',calculatedDimensions.displayImgHeight); + $('#queet-thumb-popup .modal-draggable').width(calculatedDimensions.popUpWidth); // switch image $(this).parent().removeClass('display-this-thumb'); @@ -1584,10 +1619,21 @@ $('body').on('click','#queet-thumb-popup .next-thumb',function (event) { $('body').on('click','#queet-thumb-popup .prev-thumb',function (event) { var prevImage = $(this).parent().find('.display-this-thumb').prev().children('img'); if(prevImage.length>0) { + + // start and stop youtube videos, if any + $.each($(this).parent().find('.display-this-thumb.youtube').children('iframe'),function(){ + this.contentWindow.postMessage('{"event":"command","func":"' + 'stopVideo' + '","args":""}', '*'); + }); + $.each(prevImage.parent('.youtube').children('iframe'),function(){ + this.contentWindow.postMessage('{"event":"command","func":"' + 'playVideo' + '","args":""}', '*'); + }); + // set dimensions of next image and the popup var calculatedDimensions = calculatePopUpAndImageDimensions(prevImage.attr('src')); prevImage.width(calculatedDimensions.displayImgWidth); prevImage.parent('.thumb-container').width(calculatedDimensions.displayImgWidth); + prevImage.parent('.thumb-container').children('iframe').attr('width',calculatedDimensions.displayImgWidth); + prevImage.parent('.thumb-container').children('iframe').attr('height',calculatedDimensions.displayImgHeight); $('#queet-thumb-popup .modal-draggable').width(calculatedDimensions.popUpWidth); // switch image @@ -2341,7 +2387,8 @@ $('body').on('keyup', 'div.queet-box-syntax', function(e) { // see if anyone we're following matches var suggestionsToShow = []; - var suggestionsUsernameCount = {}; + var suggestionsUsernameCount = {}; + suggestionsUsernameCount[window.loggedIn.screen_name] = 1; // any suggestions with the same screen name as mine will get their server url added $.each(window.following,function(){ var userregex = new RegExp(term); if(this.username.toLowerCase().match(userregex) || this.name.toLowerCase().match(userregex)) {