diff --git a/resources/mmv/mmv.globals.less b/resources/mmv/mmv.globals.less index 9da7ffe09..7eb1def9a 100644 --- a/resources/mmv/mmv.globals.less +++ b/resources/mmv/mmv.globals.less @@ -1,8 +1,12 @@ // Height of the area of the metadata bar which is visible without scrolling. -@metadatabar-above-fold-height: 82px; +@metadatabar-above-fold-height: 86px; -// Height of the same area in fullscreen mode (which can be slightly less since it has less controls). -@metadatabar-above-fold-fullscreen-height: 64px; +// adjust for @metadatabar-below-fold-pushup-height wide bottom padding - that area will be overlapped +// by the revealed part of the below-the-fold content +@metadatabar-above-fold-inner-height: @metadatabar-above-fold-height - @metadatabar-below-fold-pushup-height; + +// Height of the top part of the "below-fold" content which is actually above the fold, as a scrolling affordance +@metadatabar-below-fold-pushup-height: 30px; // Height of the progress bar @progress-bar-height: 14px; diff --git a/resources/mmv/mmv.lightboxinterface.less b/resources/mmv/mmv.lightboxinterface.less index 06741a4ef..15d38ff46 100644 --- a/resources/mmv/mmv.lightboxinterface.less +++ b/resources/mmv/mmv.lightboxinterface.less @@ -56,25 +56,21 @@ height: auto; color: #333333; background-color: #ffffff; - min-height: (@metadatabar-above-fold-height + 1); + min-height: (@metadatabar-above-fold-inner-height + 1); z-index: 1005; } // above-the-fold part of the metadata panel .mw-mmv-above-fold { width: 100%; - height: @metadatabar-above-fold-height; + height: @metadatabar-above-fold-inner-height; // min-height is used when the height is changed to auto to display long texts, to make sure the layout // is not messed up wheen the text is short and does not fill the available place. It is also used by // Javascript to get the "default" height. - min-height: @metadatabar-above-fold-height; + min-height: @metadatabar-above-fold-inner-height; position: relative; - border-bottom: 1px solid #eee; - - .jq-fullscreened & { - height: @metadatabar-above-fold-fullscreen-height; - min-height: @metadatabar-above-fold-fullscreen-height; - } + // make sure there is no content in the part which is overlapped by the revealed part of the below-fold content + padding-bottom: @metadatabar-below-fold-pushup-height; .mw-mmv-untruncated & { height: auto; diff --git a/resources/mmv/ui/img/time.svg b/resources/mmv/ui/img/time.svg index bf579af6e..78ad8acba 100644 --- a/resources/mmv/ui/img/time.svg +++ b/resources/mmv/ui/img/time.svg @@ -1 +1,33 @@ - \ No newline at end of file + + + + + + + + image/svg+xml + + + + + + + + diff --git a/resources/mmv/ui/img/uploader-ltr.svg b/resources/mmv/ui/img/uploader-ltr.svg new file mode 100644 index 000000000..48ea6bb40 --- /dev/null +++ b/resources/mmv/ui/img/uploader-ltr.svg @@ -0,0 +1,55 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/resources/mmv/ui/img/uploader-rtl.svg b/resources/mmv/ui/img/uploader-rtl.svg new file mode 100644 index 000000000..357d9e3f5 --- /dev/null +++ b/resources/mmv/ui/img/uploader-rtl.svg @@ -0,0 +1,55 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/resources/mmv/ui/mmv.ui.metadataPanel.js b/resources/mmv/ui/mmv.ui.metadataPanel.js index 2a9c11783..69b5c4a20 100644 --- a/resources/mmv/ui/mmv.ui.metadataPanel.js +++ b/resources/mmv/ui/mmv.ui.metadataPanel.js @@ -25,7 +25,9 @@ * @extends mw.mmv.ui.Element * @constructor * @param {jQuery} $container The container for the panel (.mw-mmv-post-image). - * @param {jQuery} $aboveFold The always-visible part of the metadata panel (.mw-mmv-above-fold). + * @param {jQuery} $aboveFold The brighter headline of the metadata panel (.mw-mmv-above-fold). + * Called "aboveFold" for historical reasons, but actually a part of the next sibling of the element + * is also above the fold (bottom of the screen). * @param {Object} localStorage the localStorage object, for dependency injection * @param {mw.mmv.Config} config A configuration object. */ @@ -154,7 +156,7 @@ } ) .addClass( 'mw-mmv-title' ); - this.title = new mw.mmv.ui.TruncatableTextField( this.$titlePara, this.$title ); + this.title = new mw.mmv.ui.TruncatableTextField( this.$titlePara, this.$title, { max: 180, small: 140 } ); this.title.setTitle( mw.message( 'multimediaviewer-title-popup-text' ), mw.message( 'multimediaviewer-title-popup-text-more' ) @@ -687,7 +689,7 @@ this.title.grow(); this.creditField.grow(); if ( this.aboveFoldIsLargerThanNormal() && !noScroll ) { - this.scroller.scrollIntoView( this.$datetimeLi, 500 ); + this.scroller.scrollIntoView( this.description.$imageDescDiv, 500 ); } }; @@ -709,7 +711,8 @@ * calling revealTruncatedText(). */ MPP.aboveFoldIsLargerThanNormal = function () { - return this.$aboveFold.height() > parseInt( this.$aboveFold.css( 'min-height' ), 10 ); + return this.$aboveFold.height() > parseInt( this.$aboveFold.css( 'min-height' ), 10 ) || + this.$credit.height() > parseInt( this.$aboveFold.css( 'padding-bottom' ), 10 ); }; mw.mmv.ui.MetadataPanel = MetadataPanel; diff --git a/resources/mmv/ui/mmv.ui.metadataPanel.less b/resources/mmv/ui/mmv.ui.metadataPanel.less index 649192398..8996bdafa 100644 --- a/resources/mmv/ui/mmv.ui.metadataPanel.less +++ b/resources/mmv/ui/mmv.ui.metadataPanel.less @@ -4,9 +4,10 @@ @info-box-color: #FFFFFF; @info-box-border-color: #DDDDDD; @info-box-border-shadow-color: #C9C9C9; - @secondary-text-color: rgb(136, 136, 136); +@fold-separator-border-width: 1px; + .mw-mmv-info-box { display: inline-block; overflow: hidden; @@ -28,7 +29,12 @@ } .mw-mmv-credit { margin: 0; - padding: 5px 0; + color: #555; + padding: 0 0 5px; + font-size: 0.85em; + &.empty { + height: 0.85em; + } } .mw-mmv-title { @@ -36,16 +42,35 @@ max-width: 60%; } - .mw-mmv-image-metadata { width: 100%; - background-color: #f5f5f5; position: relative; - padding-top: 10px; + margin-top: -@metadatabar-below-fold-pushup-height; + border-top: @fold-separator-border-width solid #ddd; + background-color: #f5f5f5; + padding-top: 4px; + + .jq-fullscreened & { + // Make sure content fits into the screen. This assumes no paddings. + height: @metadatabar-below-fold-pushup-height - @fold-separator-border-width; + overflow: hidden; + } + .jq-fullscreened .mw-mmv-untruncated & { + height: auto; + } } -.jq-fullscreened .mw-mmv-image-metadata { - display: none; +.mw-mmv-author:before { + display: inline-block; + vertical-align: middle; + height: 16px; + width: 16px; + content: ' '; + margin-right: 5px; + background-size: contain; + background-position: center center; + background-repeat: no-repeat; + background-image: url(img/user-ltr.svg); } .mw-mmv-image-desc-div { @@ -64,7 +89,7 @@ } @littlefont: 0.85em; -@mediumfont: 1em; +@mediumfont: 0.95em; .mw-mmv-caption, .mw-mmv-image-desc { @@ -107,7 +132,9 @@ &.mw-mmv-username-li:before { /* @embed */ - background-image: url(img/user-ltr.svg); + background-image: url(img/uploader-ltr.svg); + width: 18px; + margin-right: 8px; } &.mw-mmv-location-li:before { diff --git a/resources/mmv/ui/mmv.ui.stripeButtons.less b/resources/mmv/ui/mmv.ui.stripeButtons.less index 5cc457b16..b422305ec 100644 --- a/resources/mmv/ui/mmv.ui.stripeButtons.less +++ b/resources/mmv/ui/mmv.ui.stripeButtons.less @@ -13,18 +13,7 @@ @button-text-color: rgb(136, 136, 136); float: right; - margin-top: @metadatabar-above-fold-height - ( @button-height + 2 * @button-vertical-padding ); - .jq-fullscreened & { - margin-top: @metadatabar-above-fold-fullscreen-height - ( @button-height + 2 * @button-vertical-padding ); - } - .mw-mmv-untruncated & { - margin-top: 0; - border: 0; - - .mw-mmv-stripe-button-text { - display: none; - } - } + margin-top: @metadatabar-above-fold-inner-height - ( @button-height + 2 * @button-vertical-padding ); .unselectable; font-size: 1.25em; @@ -56,9 +45,6 @@ } &.has-label:before { margin-right: 0.25em; - .mw-mmv-untruncated & { - margin-right: 0; - } } &.mw-mmv-description-page-button, @@ -66,7 +52,8 @@ &.mw-mmv-description-page-button:visited { border-radius: 4px; color: white; - margin: 0.5em 1em; + padding: 7px 16px; + margin: 7px 10px; } &.mw-mmv-description-page-button.mw-mmv-repo-button-commons:before { diff --git a/tests/qunit/mmv/mmv.lightboxinterface.test.js b/tests/qunit/mmv/mmv.lightboxinterface.test.js index cbbe68ac3..1a61748f5 100644 --- a/tests/qunit/mmv/mmv.lightboxinterface.test.js +++ b/tests/qunit/mmv/mmv.lightboxinterface.test.js @@ -133,12 +133,12 @@ } ); QUnit.test( 'Fullscreen mode', 8, function ( assert ) { - var lightbox = new mw.mmv.LightboxInterface(), + var buttonOffset, panelBottom, + oldRevealButtonsAndFadeIfNeeded, + lightbox = new mw.mmv.LightboxInterface(), viewer = new mw.mmv.MultimediaViewer(), oldFnEnterFullscreen = $.fn.enterFullscreen, - oldFnExitFullscreen = $.fn.exitFullscreen, - oldRevealButtonsAndFadeIfNeeded, - buttonOffset; + oldFnExitFullscreen = $.fn.exitFullscreen; stubScrollTo(); @@ -186,12 +186,16 @@ lightbox.buttons.revealAndFadeIfNeeded = $.noop; - assert.ok( !lightbox.panel.$imageMetadata.is( ':visible' ), 'Image metadata is hidden' ); + panelBottom = $('.mw-mmv-post-image').position().top + $('.mw-mmv-post-image').height(); + + assert.ok( panelBottom === $(window).height(), 'Image metadata does not extend beyond the viewport' ); // Exiting fullscreen lightbox.buttons.$fullscreen.click(); - assert.ok( lightbox.panel.$imageMetadata.is( ':visible' ), 'Image metadata is visible' ); + panelBottom = $('.mw-mmv-post-image').position().top + $('.mw-mmv-post-image').height(); + + assert.ok( panelBottom > $(window).height(), 'Image metadata extends beyond the viewport' ); assert.ok( !lightbox.isFullscreen, 'Lightbox knows that it\'s not in fullscreen mode' ); // Unattach lightbox from document