Gilles has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/170804

Change subject: Revert layout changes
......................................................................

Revert layout changes

This reverts several commits that change the layout of 
above-the-fold/below-the-fold

Change-Id: I33a76ba9f9f29f9c45f46bc6c03475e0c51f2d09
---
M MultimediaViewer.php
M i18n/en.json
M i18n/qqq.json
M resources/mmv/mmv.globals.less
M resources/mmv/mmv.lightboxinterface.less
M resources/mmv/model/mmv.model.License.js
A resources/mmv/ui/img/drag-active.svg
A resources/mmv/ui/img/drag.svg
D resources/mmv/ui/img/pd.svg
M resources/mmv/ui/img/time.svg
D resources/mmv/ui/img/uploader-ltr.svg
D resources/mmv/ui/img/uploader-rtl.svg
M resources/mmv/ui/mmv.ui.metadataPanel.js
M resources/mmv/ui/mmv.ui.metadataPanel.less
M resources/mmv/ui/mmv.ui.metadataPanelScroller.js
M resources/mmv/ui/mmv.ui.metadataPanelScroller.less
M resources/mmv/ui/mmv.ui.stripeButtons.less
M tests/browser/features/support/pages/e2e_test_page.rb
M tests/qunit/mmv/mmv.lightboxinterface.test.js
M tests/qunit/mmv/model/mmv.model.License.test.js
M tests/qunit/mmv/ui/mmv.ui.metadataPanel.test.js
M tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js
22 files changed, 474 insertions(+), 442 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/MultimediaViewer 
refs/changes/04/170804/1

diff --git a/MultimediaViewer.php b/MultimediaViewer.php
index 5822e44..963005c 100644
--- a/MultimediaViewer.php
+++ b/MultimediaViewer.php
@@ -554,7 +554,6 @@
                        'multimediaviewer-commons-subtitle',
 
                        'multimediaviewer-credit',
-                       'multimediaviewer-credit-fallback',
 
                        'multimediaviewer-userpage-link',
 
@@ -591,6 +590,8 @@
                        'multimediaviewer-credit-popup-text',
                        'multimediaviewer-title-popup-text-more',
                        'multimediaviewer-credit-popup-text-more',
+                       'multimediaviewer-panel-open-popup-text',
+                       'multimediaviewer-panel-close-popup-text',
                ),
        ),
 
diff --git a/i18n/en.json b/i18n/en.json
index 3b97c13..3e90779 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -1,8 +1,8 @@
 {
        "@metadata": {
-               "authors": [
-                       "Mark Holmquist <mtrac...@member.fsf.org>"
-               ]
+           "authors": [
+               "Mark Holmquist <mtrac...@member.fsf.org>"
+           ]
        },
        "multimediaviewer-desc": "Expand thumbnails in a larger size in a 
fullscreen interface.",
        "multimediaviewer-desc-nil": "No description available.",
@@ -15,7 +15,6 @@
        "multimediaviewer-datetime-uploaded": "Uploaded: $1",
        "multimediaviewer-userpage-link": "{{GENDER:$2|Uploaded}} by $1",
        "multimediaviewer-credit": "$1 - $2",
-       "multimediaviewer-credit-fallback": "View author information",
        "multimediaviewer-metadata-error": "Error: Could not load image data. 
$1",
        "multimediaviewer-thumbnail-error": "Error: Could not load thumbnail 
data. $1",
        "multimediaviewer-license-cc-by-1.0": "CC BY 1.0",
@@ -109,6 +108,8 @@
        "multimediaviewer-credit-popup-text": "Author and source information",
        "multimediaviewer-title-popup-text-more": "Click to show full file 
name",
        "multimediaviewer-credit-popup-text-more": "Click to show full author 
and source",
+       "multimediaviewer-panel-open-popup-text": "More details",
+       "multimediaviewer-panel-close-popup-text": "Fewer details",
        "multimediaviewer-download-attribution-cta-header": "You need to 
attribute the author",
        "multimediaviewer-download-attribution-cta": "Show me how",
        "multimediaviewer-attr-plain": "Plain",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 5c814f9..7b65151 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -20,8 +20,7 @@
        "multimediaviewer-datetime-created": "Used in JavaScript code. 
Parameters:\n* $1 - time and date\nSee also:\n* 
{{msg-mw|Multimediaviewer-datetime-uploaded}}\n\nNote that the date comes from 
the description page and can have various forms (e.g. \"2000-01-01\", \"1st 
January 2000\", \"1492\", \"16th century\"...)\n\nAlso, this might refer to the 
date when the picture was taken, or the date when the depcited work was made - 
the usage is not consistent. You should choose a translation that works in all 
cases.\n{{Identical|Created}}",
        "multimediaviewer-datetime-uploaded": "Used in JavaScript code. 
Parameters:\n* $1 - time and date (formatted)\nSee also:\n* 
{{msg-mw|Multimediaviewer-datetime-created}}\n{{Identical|Uploaded}}",
        "multimediaviewer-userpage-link": "Link to the user page for the 
uploader of the image.\n\nUsed in JavaScript code.\n\nParameters:\n* $1 - the 
username of the uploader\n* $2 - their gender",
-       "multimediaviewer-credit": "Credit line for images. Parameters:\n* $1 - 
HTML describing the author\n* $2 - HTML describing the source\n\nNeither 
parameters are usernames, so GENDER is useless. Both come directly from the 
API, the extended metadata imageinfo prop in particular.\n\nThey will usually 
be derived from the HTML output from wikitext on a file description page - 
however, no complicated HTML, only links, will be allowed.\n\nSee also 
{{msg-mw|multimediaviewer-credit-fallback}}",
-       "multimediaviewer-credit-fallback": "Text shown in place of the credit 
line ({{msg-mw|multimediaviewer-credit}}) when neither author nor source 
information is available.",
+       "multimediaviewer-credit": "Credit line for images. Parameters:\n* $1 - 
HTML describing the author\n* $2 - HTML describing the source\n\nNeither 
parameters are usernames, so GENDER is useless. Both come directly from the 
API, the extended metadata imageinfo prop in particular.\n\nThey will usually 
be derived from the HTML output from wikitext on a file description page - 
however, no complicated HTML, only links, will be allowed.",
        "multimediaviewer-metadata-error": "Text shown when the information on 
the metadata panel could not be loaded.\n\nParameters:\n* $1 - the error 
message (not localized)\nSee also:\n* 
{{msg-mw|Multimediaviewer-thumbnail-error}}",
        "multimediaviewer-thumbnail-error": "Text shown when the image could 
not be loaded. Parameters:\n* $1 - the error message (not localized)\nSee 
also:\n* {{msg-mw|Multimediaviewer-metadata-error}}",
        "multimediaviewer-license-cc-by-1.0": "Very short label for the 
Creative Commons Attribution license, version 1.0, used in a link to the file 
information page that has more licensing information.\n{{Identical|CC BY}}",
diff --git a/resources/mmv/mmv.globals.less b/resources/mmv/mmv.globals.less
index 7eb1def..9da7ffe 100644
--- a/resources/mmv/mmv.globals.less
+++ b/resources/mmv/mmv.globals.less
@@ -1,12 +1,8 @@
 // Height of the area of the metadata bar which is visible without scrolling.
-@metadatabar-above-fold-height: 86px;
+@metadatabar-above-fold-height: 82px;
 
-// 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 same area in fullscreen mode (which can be slightly less 
since it has less controls).
+@metadatabar-above-fold-fullscreen-height: 64px;
 
 // Height of the progress bar
 @progress-bar-height: 14px;
diff --git a/resources/mmv/mmv.lightboxinterface.less 
b/resources/mmv/mmv.lightboxinterface.less
index 15d38ff..40690af 100644
--- a/resources/mmv/mmv.lightboxinterface.less
+++ b/resources/mmv/mmv.lightboxinterface.less
@@ -56,21 +56,25 @@
        height: auto;
        color: #333333;
        background-color: #ffffff;
-       min-height: (@metadatabar-above-fold-inner-height + 1);
+       min-height: (@metadatabar-above-fold-height + 1);
        z-index: 1005;
 }
 
 // above-the-fold part of the metadata panel
 .mw-mmv-above-fold {
        width: 100%;
-       height: @metadatabar-above-fold-inner-height;
+       height: @metadatabar-above-fold-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-inner-height;
+       min-height: @metadatabar-above-fold-height;
        position: relative;
-       // 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;
+       border-bottom: 1px solid #dddddd;
+
+       .jq-fullscreened & {
+               height: @metadatabar-above-fold-fullscreen-height;
+               min-height: @metadatabar-above-fold-fullscreen-height;
+       }
 
        .mw-mmv-untruncated & {
                height: auto;
diff --git a/resources/mmv/model/mmv.model.License.js 
b/resources/mmv/model/mmv.model.License.js
index 8e076e8..abe651f 100644
--- a/resources/mmv/model/mmv.model.License.js
+++ b/resources/mmv/model/mmv.model.License.js
@@ -64,14 +64,6 @@
        };
 
        /**
-        * Check whether this is a public domain "license".
-        * @returns {boolean}
-        */
-       LP.isPd = function () {
-               return this.internalName === 'pd';
-       };
-
-       /**
         * Returns the short name of the license:
         * - if we have interface messages for this license (basically just CC 
and PD), use those
         * - otherwise use the short name from the license template (might or 
might not be translated
diff --git a/resources/mmv/ui/img/drag-active.svg 
b/resources/mmv/ui/img/drag-active.svg
new file mode 100644
index 0000000..5843f00
--- /dev/null
+++ b/resources/mmv/ui/img/drag-active.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   version="1.1"
+   width="100%"
+   height="100%"
+   viewBox="0 0 30 16"
+   id="Layer_1"
+   xml:space="preserve"><metadata
+   id="metadata9"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage"; 
/><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs7" />
+<path
+   d="m 24.5,12.2 c -0.2,0 -0.4,0 -0.5,-0.1 L 15,6.9 6,12.1 C 5.8,12.2 
5.7,12.2 5.5,12.2 5.1,12.2 4.8,12 4.6,11.7 L 4.2,11 C 4,10.8 4,10.5 4.1,10.2 
4.2,9.9 4.3,9.7 4.6,9.6 l 10.1,-5.8 0.4,0 0.1,0 h 0.2 l 0.2,0.1 9.9,5.7 c 
0.2,0.1 0.4,0.4 0.5,0.6 0.1,0.3 0,0.5 -0.1,0.8 l -0.4,0.7 c -0.3,0.3 -0.6,0.5 
-1,0.5 z"
+   id="path3"
+   style="fill:#ffffff" />
+</svg>
\ No newline at end of file
diff --git a/resources/mmv/ui/img/drag.svg b/resources/mmv/ui/img/drag.svg
new file mode 100644
index 0000000..c116cf4
--- /dev/null
+++ b/resources/mmv/ui/img/drag.svg
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   version="1.1"
+   width="100%"
+   height="100%"
+   viewBox="0 0 30 16"
+   id="Layer_1"
+   xml:space="preserve"><metadata
+   id="metadata9"><rdf:RDF><cc:Work
+       rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+         rdf:resource="http://purl.org/dc/dcmitype/StillImage"; 
/><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+   id="defs7" />
+<path
+   d="m 24.5,12.2 c -0.2,0 -0.4,0 -0.5,-0.1 L 15,6.9 6,12.1 C 5.8,12.2 
5.7,12.2 5.5,12.2 5.1,12.2 4.8,12 4.6,11.7 L 4.2,11 C 4,10.8 4,10.5 4.1,10.2 
4.2,9.9 4.3,9.7 4.6,9.6 l 10.1,-5.8 0.4,0 0.1,0 h 0.2 l 0.2,0.1 9.9,5.7 c 
0.2,0.1 0.4,0.4 0.5,0.6 0.1,0.3 0,0.5 -0.1,0.8 l -0.4,0.7 c -0.3,0.3 -0.6,0.5 
-1,0.5 z"
+   id="path3"
+   style="fill:#555555" />
+</svg>
\ No newline at end of file
diff --git a/resources/mmv/ui/img/pd.svg b/resources/mmv/ui/img/pd.svg
deleted file mode 100644
index eb4d750..0000000
--- a/resources/mmv/ui/img/pd.svg
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/";
-   xmlns:cc="http://creativecommons.org/ns#";
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
-   xmlns:svg="http://www.w3.org/2000/svg";
-   xmlns="http://www.w3.org/2000/svg";
-   version="1.0"
-   width="64"
-   height="64"
-   viewBox="5.5 -3.5 64 64"
-   id="svg2">
-  <metadata
-     id="metadata12">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs10" />
-  <g
-     transform="matrix(0.89136054,0,0,0.89136054,431.08023,-311.5986)"
-     id="g29">
-    <path
-       d="m -434,375.8 c -0.2,-1.5 -0.7,-2.8 -1.5,-3.9 -1.1,-1.6 -2.9,-2.4 
-5.3,-2.4 -3.4,0 -5.8,1.7 -7.1,5.1 -0.7,1.8 -1,4.2 -1,7.2 0,2.9 0.3,5.1 1,6.9 
1.2,3.2 3.5,4.9 6.9,4.9 2.4,0 4.1,-0.6 5.1,-1.9 1,-1.3 1.6,-3 1.8,-5 h 10.4 c 
-0.2,3.1 -1.4,6 -3.4,8.8 -3.2,4.5 -7.9,6.7 -14.2,6.7 -6.3,0 -10.9,-1.9 
-13.8,-5.6 -3,-3.7 -4.4,-8.5 -4.4,-14.5 0,-6.7 1.6,-11.9 4.9,-15.6 3.3,-3.7 
7.8,-5.6 13.5,-5.6 4.9,0 8.9,1.1 12,3.3 3.1,2.2 5,6.1 5.5,11.6 H -434 z"
-       id="path31"
-       style="fill:#939598" />
-  </g>
-  <g
-     transform="translate(0,80)"
-     id="g3410">
-    <path
-       d="m 37.35,-83.5 c 9,0 16.6,3.1 22.9,9.4 3,3 5.3,6.4 6.9,10.3 1.6,3.9 
2.3,8 2.3,12.3 0,4.4 -0.8,8.5 -2.3,12.3 -1.5,3.8 -3.8,7.2 -6.8,10.1 -3.1,3.1 
-6.7,5.4 -10.6,7.1 -4,1.6 -8.1,2.5 -12.3,2.5 -4.2,0 -8.3,-0.8 -12.1,-2.4 
-3.9,-1.6 -7.3,-4 -10.4,-7 -3.1,-3.1 -5.4,-6.5 -7,-10.4 -1.6,-3.8 -2.4,-7.9 
-2.4,-12.2 0,-4.2 0.8,-8.3 2.4,-12.2 1.6,-3.9 4,-7.4 7.1,-10.5 5.9,-6.2 
13.4,-9.3 22.3,-9.3 l 0,0 z m 0.1,5.8 c -7.3,0 -13.5,2.6 -18.5,7.7 -2.5,2.6 
-4.4,5.4 -5.8,8.6 -1.4,3.2 -2,6.5 -2,10 0,3.4 0.7,6.7 2,9.9 1.4,3.2 3.3,6 
5.8,8.5 2.5,2.5 5.4,4.4 8.5,5.7 3.2,1.3 6.5,2 9.9,2 3.4,0 6.8,-0.7 10,-2 
3.2,-1.3 6.1,-3.3 8.7,-5.8 5,-4.9 7.5,-11 7.5,-18.3 0,-3.5 -0.6,-6.9 -1.9,-10.1 
-1.3,-3.2 -3.2,-6 -5.7,-8.5 -5.1,-5.1 -11.3,-7.7 -18.5,-7.7 l 0,0 z"
-       id="path6-0_1_-2"
-       style="fill:#939598" />
-    <rect
-       width="8.5010338"
-       height="55.099468"
-       x="5.6489754"
-       y="35.382771"
-       transform="matrix(-0.70710678,-0.70710678,0.70710678,-0.70710678,0,0)"
-       id="rect3025-8_1_-4"
-       style="fill:#939598" />
-  </g>
-</svg>
diff --git a/resources/mmv/ui/img/time.svg b/resources/mmv/ui/img/time.svg
index 78ad8ac..bf579af 100644
--- a/resources/mmv/ui/img/time.svg
+++ b/resources/mmv/ui/img/time.svg
@@ -1,33 +1 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/";
-   xmlns:cc="http://creativecommons.org/ns#";
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
-   xmlns:svg="http://www.w3.org/2000/svg";
-   xmlns="http://www.w3.org/2000/svg";
-   version="1.1"
-   width="80"
-   height="80"
-   viewBox="0 0 80 80"
-   id="svg2">
-  <metadata
-     id="metadata10">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs8" />
-  <path
-     d="M 64.741719,15.24625 C 58.139844,8.637812 49.350469,5 39.995625,5 
30.648437,5 21.859062,8.637812 15.241875,15.24625 8.6334375,21.855781 
5,30.649531 5,40 5,49.350469 8.6334375,58.144219 15.241875,64.741719 
21.859062,71.35125 30.648437,75 39.995625,75 49.350469,75 58.139844,71.35125 
64.741719,64.741719 71.353437,58.144219 75,49.350469 75,40 75,30.649531 
71.353437,21.855781 64.741719,15.24625 z M 51.459219,56.535313 
36.504375,41.604531 V 16.009687 h 5.627344 v 23.234532 l 13.301094,13.30875 
-3.973594,3.982344 z"
-     id="path4"
-     style="fill:#929497" />
-</svg>
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg"; 
width="80" height="80" viewBox="0 0 80 80"><path fill="#929497" d="M62.621 
17.368c-6.036-6.042-14.072-9.368-22.625-9.368-8.546 0-16.582 3.326-22.632 
9.368-6.042 6.043-9.364 14.083-9.364 22.632s3.322 16.589 9.364 22.621c6.05 
6.043 14.086 9.379 22.632 9.379 8.553 0 16.589-3.336 22.625-9.379 6.045-6.032 
9.379-14.072 9.379-22.621s-3.334-16.589-9.379-22.632zm-12.144 
37.75l-13.673-13.651v-23.401h5.145v21.243l12.161 12.168-3.633 3.641z"/></svg>
\ No newline at end of file
diff --git a/resources/mmv/ui/img/uploader-ltr.svg 
b/resources/mmv/ui/img/uploader-ltr.svg
deleted file mode 100644
index 48ea6bb..0000000
--- a/resources/mmv/ui/img/uploader-ltr.svg
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/";
-   xmlns:cc="http://creativecommons.org/ns#";
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
-   xmlns:svg="http://www.w3.org/2000/svg";
-   xmlns="http://www.w3.org/2000/svg";
-   version="1.1"
-   width="85"
-   height="80"
-   id="svg2">
-  <metadata
-     id="metadata16">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs14" />
-  <g
-     transform="matrix(1.6614596,0,0,1.6614596,-73.590709,-26.97237)"
-     id="g3008">
-    <path
-       d="m 77.735565,53.958696 0,-11.374448 H 70.228429 L 80.692921,32.574733 
V 22.110241 H 48.616978 c -4.54978,0 -4.322291,3.867312 -4.322291,4.094801 v 
32.303433 h 31.165988 c 4.54978,0 4.777268,-4.549779 4.777268,-4.549779 h 
-2.502378 z"
-       id="path3"
-       style="fill:#8e9093" />
-    <path
-       d="m 57.034069,32.119755 c 1.364934,0 2.729868,1.137445 
2.729868,2.729868 0,1.364934 -1.137445,2.729867 -2.729868,2.729867 -1.364934,0 
-2.729867,-1.137444 -2.729867,-2.729867 0.227489,-1.592423 1.364933,-2.729868 
2.729867,-2.729868 z"
-       id="path5"
-       style="fill:#ffffff" />
-    <circle
-       cx="444.5"
-       cy="379.5"
-       r="1.2"
-       transform="matrix(2.2748896,0,0,2.2748896,-943.0074,-828.69849)"
-       id="circle7"
-       style="fill:#ffffff" />
-    <path
-       d="m 62.493804,49.863894 c -4.094801,0 -7.962113,-1.364933 
-10.237003,-3.639823 -0.682467,-0.682467 -0.682467,-1.592423 0,-2.047401 
0.682467,-0.682467 1.592423,-0.682467 2.047401,0 1.819911,1.819912 
5.004757,2.729868 8.189602,2.729868 3.184846,0 6.369691,-1.137445 
8.189603,-2.729868 0.682467,-0.682467 1.592423,-0.454978 2.047401,0 
0.682467,0.682467 0.454978,1.592423 0,2.047401 -2.27489,2.502379 
-6.142202,3.639823 -10.237004,3.639823 z"
-       id="path9"
-       style="fill:#ffffff" />
-    <path
-       d="m 81.661879,51.699079 8.619227,0 0,-11.46882 5.171538,0 
-9.193844,-8.810768 -9.768459,8.810768 5.171538,0 z"
-       id="Shape_6_"
-       style="fill:#8e9093" />
-  </g>
-</svg>
diff --git a/resources/mmv/ui/img/uploader-rtl.svg 
b/resources/mmv/ui/img/uploader-rtl.svg
deleted file mode 100644
index 357d9e3..0000000
--- a/resources/mmv/ui/img/uploader-rtl.svg
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-
-<svg
-   xmlns:dc="http://purl.org/dc/elements/1.1/";
-   xmlns:cc="http://creativecommons.org/ns#";
-   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
-   xmlns:svg="http://www.w3.org/2000/svg";
-   xmlns="http://www.w3.org/2000/svg";
-   version="1.1"
-   width="80"
-   height="80"
-   id="svg2">
-  <metadata
-     id="metadata16">
-    <rdf:RDF>
-      <cc:Work
-         rdf:about="">
-        <dc:format>image/svg+xml</dc:format>
-        <dc:type
-           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
-        <dc:title></dc:title>
-      </cc:Work>
-    </rdf:RDF>
-  </metadata>
-  <defs
-     id="defs14" />
-  <g
-     transform="matrix(1.5559847,0,0,1.5559847,-68.918929,-22.720744)"
-     id="g3008">
-    <path
-       d="m 62.009885,53.958696 0,-11.374448 h 7.507136 L 59.052529,32.574733 
V 22.110241 h 32.075943 c 4.54978,0 4.322291,3.867312 4.322291,4.094801 V 
58.508475 H 64.284775 c -4.54978,0 -4.777268,-4.549779 -4.777268,-4.549779 h 
2.502378 z"
-       id="path3"
-       style="fill:#8e9093" />
-    <path
-       d="m 82.711381,32.119755 c -1.364934,0 -2.729868,1.137445 
-2.729868,2.729868 0,1.364934 1.137445,2.729867 2.729868,2.729867 1.364934,0 
2.729867,-1.137444 2.729867,-2.729867 -0.227489,-1.592423 -1.364933,-2.729868 
-2.729867,-2.729868 z"
-       id="path5"
-       style="fill:#ffffff" />
-    <circle
-       cx="444.5"
-       cy="379.5"
-       r="1.2"
-       transform="matrix(-2.2748896,0,0,2.2748896,1082.7528,-828.69849)"
-       id="circle7"
-       style="fill:#ffffff" />
-    <path
-       d="m 77.251646,49.863894 c 4.094801,0 7.962113,-1.364933 
10.237003,-3.639823 0.682467,-0.682467 0.682467,-1.592423 0,-2.047401 
-0.682467,-0.682467 -1.592423,-0.682467 -2.047401,0 -1.819911,1.819912 
-5.004757,2.729868 -8.189602,2.729868 -3.184846,0 -6.369691,-1.137445 
-8.189603,-2.729868 -0.682467,-0.682467 -1.592423,-0.454978 -2.047401,0 
-0.682467,0.682467 -0.454978,1.592423 0,2.047401 2.27489,2.502379 
6.142202,3.639823 10.237004,3.639823 z"
-       id="path9"
-       style="fill:#ffffff" />
-    <path
-       d="m 58.083571,51.699079 -8.619227,0 0,-11.46882 -5.171538,0 
9.193844,-8.810768 9.768459,8.810768 -5.171538,0 z"
-       id="Shape_6_"
-       style="fill:#8e9093" />
-  </g>
-</svg>
diff --git a/resources/mmv/ui/mmv.ui.metadataPanel.js 
b/resources/mmv/ui/mmv.ui.metadataPanel.js
index 6bf3608..6a1afee 100644
--- a/resources/mmv/ui/mmv.ui.metadataPanel.js
+++ b/resources/mmv/ui/mmv.ui.metadataPanel.js
@@ -25,9 +25,7 @@
         * @extends mw.mmv.ui.Element
         * @constructor
         * @param {jQuery} $container The container for the panel 
(.mw-mmv-post-image).
-        * @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 {jQuery} $aboveFold The always-visible  part of the metadata 
panel (.mw-mmv-above-fold).
         * @param {Object} localStorage the localStorage object, for dependency 
injection
         * @param {mw.mmv.Config} config A configuration object.
         */
@@ -91,6 +89,9 @@
        MPP.empty = function () {
                this.scroller.empty();
 
+               this.$license.empty().addClass( 'empty' );
+               this.$permissionLink.hide();
+
                this.buttons.empty();
 
                this.description.empty();
@@ -100,10 +101,6 @@
                this.$title.empty().removeClass( 'error' );
                this.$authorAndSource.empty();
                this.$credit.addClass( 'empty' );
-
-               this.$license.empty().prop( 'href', '#' );
-               this.$licenseLi.addClass( 'empty' );
-               this.$permissionLink.hide();
 
                this.$username.empty();
                this.$usernameLi.addClass( 'empty' );
@@ -138,7 +135,29 @@
                this.$container.append( this.$aboveFold );
 
                this.initializeButtons(); // float, needs to be on top
+               this.initializeTitleAndCredit();
+               this.initializeLicense();
+       };
+
+       /**
+        * Initializes the title and credit elements.
+        */
+       MPP.initializeTitleAndCredit = function () {
+               var self = this;
+
+               this.$titleAndCredit = $( '<div>' )
+                       .addClass( 'mw-mmv-title-credit' )
+                       // Since these elements are created dynamically, we 
listen this way for logging purposes
+                       .on( 'click', '.mw-mmv-author a', function ( e ) {
+                               self.trackLinkClick.call( this, 'author-page', 
e );
+                       } )
+                       .on( 'click', '.mw-mmv-source a', function ( e ) {
+                               self.trackLinkClick.call( this, 'source-page', 
e );
+                       } )
+                       .appendTo( this.$titleDiv );
+
                this.initializeTitle();
+               this.initializeCredit();
        };
 
        /**
@@ -147,7 +166,7 @@
        MPP.initializeTitle = function () {
                this.$titlePara = $( '<p>' )
                        .addClass( 'mw-mmv-title-para' )
-                       .appendTo( this.$aboveFold );
+                       .appendTo( this.$titleAndCredit );
 
                this.$title = $( '<span>' )
                        .tipsy( {
@@ -156,15 +175,69 @@
                        } )
                        .addClass( 'mw-mmv-title' );
 
-               this.title = new mw.mmv.ui.TruncatableTextField( 
this.$titlePara, this.$title, { max: 180, small: 140 } );
+               this.title = new mw.mmv.ui.TruncatableTextField( 
this.$titlePara, this.$title );
                this.title.setTitle(
                        mw.message( 'multimediaviewer-title-popup-text' ),
                        mw.message( 'multimediaviewer-title-popup-text-more' )
                );
        };
 
+       /**
+        * Initializes the credit elements.
+        */
+       MPP.initializeCredit = function () {
+               this.$credit = $( '<p>' )
+                       .addClass( 'mw-mmv-credit empty' )
+                       .appendTo( this.$titleAndCredit );
+
+               // we need an inline container for tipsy, otherwise it would be 
centered weirdly
+               this.$authorAndSource = $( '<span>' )
+                       .addClass( 'mw-mmv-source-author' )
+                       .tipsy( {
+                               delayIn: mw.config.get( 'wgMultimediaViewer' 
).tooltipDelay,
+                               gravity: this.correctEW( 'sw' )
+                       } );
+
+               this.creditField = new mw.mmv.ui.TruncatableTextField(
+                       this.$credit,
+                       this.$authorAndSource,
+                       { max: 200, small: 160 }
+               );
+
+               this.creditField.setTitle(
+                       mw.message( 'multimediaviewer-credit-popup-text' ),
+                       mw.message( 'multimediaviewer-credit-popup-text-more' )
+               );
+       };
+
+       /**
+        * Initializes the license elements.
+        */
+       MPP.initializeLicense = function () {
+               var panel = this;
+
+               this.$license = $( '<a>' )
+                       .addClass( 'mw-mmv-license empty' )
+                       .prop( 'href', '#' )
+                       .appendTo( this.$titlePara )
+                       .on( 'click', function( e ) {
+                               panel.trackLinkClick.call( this, 
'license-page', e );
+                       } );
+
+               this.$permissionLink = $( '<span>' )
+                       .addClass( 'mw-mmv-permission-link mw-mmv-label' )
+                       .text( mw.message( 'multimediaviewer-permission-link' 
).text() )
+                       .appendTo( this.$titlePara )
+                       .hide()
+                       .on( 'click', function() {
+                               panel.permission.grow();
+                               panel.scroller.scrollIntoView( 
panel.permission.$box, 500 );
+                               return false;
+                       } );
+       };
+
        MPP.initializeButtons = function () {
-               this.buttons = new mw.mmv.ui.StripeButtons( this.$titleDiv );
+               this.buttons = new mw.mmv.ui.StripeButtons( this.$titleDiv, 
this.localStorage );
        };
 
        /**
@@ -183,50 +256,9 @@
                        .addClass( 'mw-mmv-image-metadata-column 
mw-mmv-image-metadata-links-column' )
                        .appendTo( this.$imageMetadata );
 
-               this.initializeCredit();
                this.description = new mw.mmv.ui.Description( 
this.$imageMetadataLeft );
                this.permission = new mw.mmv.ui.Permission( 
this.$imageMetadataLeft );
                this.initializeImageLinks();
-       };
-
-       /**
-        * Initializes the credit elements.
-        */
-       MPP.initializeCredit = function () {
-               var panel = this;
-
-               this.$credit = $( '<p>' )
-                       .addClass( 'mw-mmv-credit empty' )
-                       .appendTo( this.$imageMetadataLeft )
-                       .on( 'click.mmv-mp', '.mw-mmv-credit-fallback', 
function ( e ) {
-                               panel.trackLinkClick( this, 'author-page', e );
-                       } );
-
-               // we need an inline container for tipsy, otherwise it would be 
centered weirdly
-               this.$authorAndSource = $( '<span>' )
-                       .addClass( 'mw-mmv-source-author' )
-                       .tipsy( {
-                               delayIn: mw.config.get( 'wgMultimediaViewer' 
).tooltipDelay,
-                               gravity: this.correctEW( 'sw' )
-                       } )
-                       .on( 'click', '.mw-mmv-author a', function ( e ) {
-                               panel.trackLinkClick.call( this, 'author-page', 
e );
-                       } )
-                       .on( 'click', '.mw-mmv-source a', function ( e ) {
-                               panel.trackLinkClick.call( this, 'source-page', 
e );
-                       } );
-
-
-               this.creditField = new mw.mmv.ui.TruncatableTextField(
-                       this.$credit,
-                       this.$authorAndSource,
-                       { max: 200, small: 160 }
-               );
-
-               this.creditField.setTitle(
-                       mw.message( 'multimediaviewer-credit-popup-text' ),
-                       mw.message( 'multimediaviewer-credit-popup-text-more' )
-               );
        };
 
        /**
@@ -241,40 +273,9 @@
                        .addClass( 'mw-mmv-image-links' )
                        .appendTo( this.$imageLinkDiv );
 
-               this.initializeLicense();
                this.initializeUploader();
                this.initializeDatetime();
                this.initializeLocation();
-       };
-
-       /**
-        * Initializes the license elements.
-        */
-       MPP.initializeLicense = function () {
-               var panel = this;
-
-               this.$licenseLi = $( '<li>' )
-                       .addClass( 'mw-mmv-license-li empty')
-                       .appendTo( this.$imageLinks );
-
-               this.$license = $( '<a>' )
-                       .addClass( 'mw-mmv-license' )
-                       .prop( 'href', '#' )
-                       .appendTo( this.$licenseLi )
-                       .on( 'click', function( e ) {
-                               panel.trackLinkClick.call( this, 
'license-page', e );
-                       } );
-
-               this.$permissionLink = $( '<span>' )
-                       .addClass( 'mw-mmv-permission-link mw-mmv-label' )
-                       .text( mw.message( 'multimediaviewer-permission-link' 
).text() )
-                       .appendTo( this.$licenseLi )
-                       .hide()
-                       .on( 'click', function() {
-                               panel.permission.grow();
-                               panel.scroller.scrollIntoView( 
panel.permission.$box, 500 );
-                               return false;
-                       } );
        };
 
        /**
@@ -409,59 +410,60 @@
        };
 
        /**
-        * Set source and author.
+        * Bignasty function for setting source and author. Both #setAuthor and
+        * #setSource use this with some shortcuts.
         * @param {string} source With unsafe HTML
         * @param {string} author With unsafe HTML
-        * @param {string} filepageUrl URL of the file page (used when other 
data is not available)
         */
-       MPP.setCredit = function ( source, author, filepageUrl ) {
-               // sanitization will be done by TruncatableTextField.set()
+       MPP.setCredit = function ( source, author ) {
+               this.source = source || null;
+               this.author = author || null;
+
                if ( author && source ) {
                        this.creditField.set(
                                mw.message(
                                        'multimediaviewer-credit',
-                                       this.wrapAuthor( author ),
-                                       this.wrapSource( source )
+                                       this.author,
+                                       this.source
                                ).plain()
                        );
                } else if ( author ) {
-                       this.creditField.set( this.wrapAuthor( author ) );
+                       this.creditField.set( this.author );
                } else if ( source ) {
-                       this.creditField.set( this.wrapSource( source ) );
-               } else {
-                       this.creditField.set(
-                               $( '<a>' )
-                                       .addClass( 'mw-mmv-credit-fallback' )
-                                       .prop( 'href', filepageUrl )
-                                       .text( mw.message( 
'multimediaviewer-credit-fallback' ).plain() )
-                       );
+                       this.creditField.set( this.source );
                }
 
-               this.$credit.removeClass( 'empty' );
+               this.$credit.toggleClass( 'empty', !author && !source );
        };
 
        /**
-        * Wraps a source string it with MediaViewer styles
+        * Sets the source in the panel
         * @param {string} source Warning - unsafe HTML sometimes goes here
-        * @return {string} unsafe HTML
         */
-       MPP.wrapSource = function ( source ) {
-               return $( '<span>' )
-                       .addClass( 'mw-mmv-source' )
-                       .append( $.parseHTML( source ) )
-                       .get( 0 ).outerHTML;
+       MPP.setSource = function ( source ) {
+               if ( source ) {
+                       source = $( '<span>' )
+                               .addClass( 'mw-mmv-source' )
+                               .append( $.parseHTML( source ) )
+                               .get( 0 ).outerHTML;
+               }
+
+               this.setCredit( source, this.author );
        };
 
        /**
-        * Wraps an author string with MediaViewer styles
+        * Sets the author in the panel
         * @param {string} author Warning - unsafe HTML sometimes goes here
-        * @return {string} unsafe HTML
         */
-       MPP.wrapAuthor = function ( author ) {
-               return $( '<span>' )
-                       .addClass( 'mw-mmv-author' )
-                       .append( $.parseHTML( author ) )
-                       .get( 0 ).outerHTML;
+       MPP.setAuthor = function ( author ) {
+               if ( author ) {
+                       author = $( '<span>' )
+                               .addClass( 'mw-mmv-author' )
+                               .append( $.parseHTML( author ) )
+                               .get( 0 ).outerHTML;
+               }
+
+               this.setCredit( this.source, author );
        };
 
        /**
@@ -470,28 +472,25 @@
         * @param {string} filePageUrl URL of the file description page
         */
        MPP.setLicense = function ( license, filePageUrl ) {
-               var shortName, url, isCc, isPd;
+               var shortName, url, isCc;
 
                if ( license ) {
                        shortName = license.getShortName();
                        url = license.deedUrl || filePageUrl;
                        isCc = license.isCc();
-                       isPd = license.isPd();
                } else {
                        shortName = mw.message( 
'multimediaviewer-license-default' ).text();
                        url = filePageUrl;
-                       isCc = isPd = false;
+                       isCc = false;
                }
 
                this.$license
                        .text( shortName )
+                       .toggleClass( 'cc-license', isCc )
                        .prop( 'href', url )
                        .prop( 'target', license && license.deedUrl ? '_blank' 
: '' );
 
-               this.$licenseLi
-                       .toggleClass( 'cc-license', isCc )
-                       .toggleClass( 'pd-license', isPd )
-                       .removeClass( 'empty' );
+               this.$license.removeClass( 'empty' );
        };
 
        /**
@@ -606,7 +605,13 @@
                        } );
                }
 
-               this.setCredit( imageData.source, imageData.author, 
imageData.descriptionUrl );
+               if ( imageData.source ) {
+                       this.setSource( imageData.source );
+               }
+
+               if ( imageData.author ) {
+                       this.setAuthor( imageData.author );
+               }
 
                this.buttons.set( imageData, repoData );
                this.description.set( imageData.description, image.caption );
@@ -687,7 +692,7 @@
                this.title.grow();
                this.creditField.grow();
                if ( this.aboveFoldIsLargerThanNormal() && !noScroll ) {
-                       this.scroller.scrollIntoView( 
this.description.$imageDescDiv, 500 );
+                       this.scroller.scrollIntoView( this.$datetimeLi, 500 );
                }
        };
 
@@ -709,8 +714,7 @@
         * calling revealTruncatedText().
         */
        MPP.aboveFoldIsLargerThanNormal = function () {
-               return this.$aboveFold.height() > parseInt( 
this.$aboveFold.css( 'min-height' ), 10 ) ||
-                       this.$credit.height() > parseInt( this.$aboveFold.css( 
'padding-bottom' ), 10 );
+               return this.$aboveFold.height() > parseInt( 
this.$aboveFold.css( 'min-height' ), 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 e3495c0..ba59a31 100644
--- a/resources/mmv/ui/mmv.ui.metadataPanel.less
+++ b/resources/mmv/ui/mmv.ui.metadataPanel.less
@@ -4,9 +4,8 @@
 @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;
+@secondary-text-color: rgb(136, 136, 136);
 
 .mw-mmv-info-box {
        display: inline-block;
@@ -29,12 +28,7 @@
 }
 .mw-mmv-credit {
        margin: 0;
-       color: #555;
-       padding: 0 0 5px;
-       font-size: 0.85em;
-       &.empty {
-               height: 0.85em;
-       }
+       padding: 5px 0;
 }
 
 .mw-mmv-title {
@@ -44,33 +38,13 @@
 
 .mw-mmv-image-metadata {
        width: 100%;
+       background-color: #fbfbfb;
        position: relative;
-       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;
-       }
+       padding-top: 10px;
 }
 
-.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);
+.jq-fullscreened .mw-mmv-image-metadata {
+       display: none;
 }
 
 .mw-mmv-image-desc-div {
@@ -89,7 +63,7 @@
 }
 
 @littlefont: 0.85em;
-@mediumfont: 0.95em;
+@mediumfont: 1em;
 
 .mw-mmv-caption,
 .mw-mmv-image-desc {
@@ -120,16 +94,6 @@
                        background-repeat: no-repeat;
                }
 
-               &.mw-mmv-license-li.cc-license:before {
-                       /* @embed */
-                       background-image: url(img/cc.svg);
-               }
-
-               &.mw-mmv-license-li.pd-license:before {
-                       /* @embed */
-                       background-image: url(img/pd.svg);
-               }
-
                &.mw-mmv-datetime-li:before {
                        /* @embed */
                        background-image: url(img/time.svg);
@@ -137,9 +101,7 @@
 
                &.mw-mmv-username-li:before {
                        /* @embed */
-                       background-image: url(img/uploader-ltr.svg);
-                       width: 18px;
-                       margin-right: 8px;
+                       background-image: url(img/user-ltr.svg);
                }
 
                &.mw-mmv-location-li:before {
@@ -147,9 +109,94 @@
                        background-image: url(img/location.svg);
                }
 
+               &.mw-mmv-repo-li:before {
+                       display: none;
+               }
+
                &.empty:before {
                        background-image: none !important;
                }
+       }
+}
+
+.mw-mmv-repo-li {
+       @padding: 5px;
+       @icon-size: 16px;
+
+       display: block;
+       min-height: @icon-size;
+       border: 1px solid @info-box-border-color;
+       .box-round(5px);
+       padding: @padding;
+       padding-left: @icon-size + 2 * @padding;
+       margin-top: 10px;
+
+       /* @embed */
+       background-image: url(img/repo.svg);
+       background-repeat: no-repeat;
+       background-size: auto @icon-size;
+       // icon should be positioned with consistent padding, but using 
absolute lengths is not RTL-compatible
+       // so we use percentages (looks a bit off) for older browsers and 
four-value syntax for newer ones;
+       // MediaWiki flips 'left' keywords automatically
+       background-position: 2% center;
+       background-position: left @padding center;
+
+       background-color: @info-box-color;
+
+       line-height: 1.3;
+
+       &.commons { // there is an extra subtitle for Commons images, box 
should be larger
+               /* @embed */
+               background-image: url(img/commons.svg);
+               @icon-size: 32px;
+               min-height: @icon-size;
+               padding-left: @icon-size + 2 * @padding;
+               background-size: auto @icon-size;
+               background-position: 3% center;
+               background-position: left @padding+4px center;
+       }
+
+       .mw-mmv-repo,
+       .mw-mmv-repo-subtitle {
+               display: block;
+       }
+
+       .mw-mmv-repo-subtitle {
+               color: @secondary-text-color;
+               font-size: small;
+       }
+}
+
+.mw-mmv-title-credit {
+
+       height: @metadatabar-above-fold-height;
+       .jq-fullscreened & {
+               height: @metadatabar-above-fold-fullscreen-height;
+       }
+       .mw-mmv-untruncated & {
+               height: auto;
+       }
+}
+
+.mw-mmv-license {
+       color: #888888;
+       font-size: 0.9em;
+       padding: 0 10px; // pad both sides; depending on the language of the 
image name, this might end up on either side
+
+       &.empty {
+               display: none;
+       }
+
+       &.cc-license:before {
+               background-size: contain;
+               /* @embed */
+               background-image: url(img/cc.svg);
+               display: inline-block;
+               vertical-align: text-bottom;
+               height: 20px;
+               width: 20px;
+               content: ' ';
+               /* @noflip */ margin-right: 5px; // :before is not flipped 
either
        }
 }
 
@@ -217,17 +264,7 @@
 }
 
 .mw-mmv-image-metadata-links-column {
-       max-width: 33.5%;
-       width: 25%;
-       text-align: right;
-       float: right;
-       transition: width 0.2s ease-out;
-
-       .panel-open & {
-               width: 33.5%;
-               text-align: left;
-       }
-
+       width: 33.5%;
 }
 
 .mw-mmv-permission-link {
diff --git a/resources/mmv/ui/mmv.ui.metadataPanelScroller.js 
b/resources/mmv/ui/mmv.ui.metadataPanelScroller.js
index 140029d..2b12e93 100644
--- a/resources/mmv/ui/mmv.ui.metadataPanelScroller.js
+++ b/resources/mmv/ui/mmv.ui.metadataPanelScroller.js
@@ -73,6 +73,7 @@
                this.$container.on( 'mmv-metadata-open', function () {
                        if ( !panel.hasOpenedMetadata && panel.localStorage ) {
                                panel.hasOpenedMetadata = true;
+                               panel.$dragIcon.removeClass( 
'panel-never-opened' );
                                try {
                                        panel.localStorage.setItem( 
'mmv.hasOpenedMetadata', true );
                                } catch ( e ) {
@@ -92,6 +93,8 @@
        };
 
        MPSP.empty = function () {
+               this.$dragIcon.toggleClass( 'panel-never-opened', 
!this.hasOpenedMetadata );
+
                // need to remove this to avoid animating again when reopening 
lightbox on same page
                this.$container.removeClass( 'invite' );
 
@@ -99,6 +102,36 @@
        };
 
        MPSP.initialize = function () {
+               var panel = this;
+
+               this.$dragIcon = $( '<div>' )
+                       .addClass( 'mw-mmv-drag-icon 
mw-mmv-drag-icon-pointing-down' )
+                       .toggleClass( 'panel-never-opened', 
!this.hasOpenedMetadata )
+                       .prop( 'title', mw.message( 
'multimediaviewer-panel-open-popup-text' ).text() )
+                       .tipsy( { gravity: 's', delayIn: mw.config.get( 
'wgMultimediaViewer').tooltipDelay } )
+                       .appendTo( this.$aboveFold )
+                       .click( function () {
+                               // Trigger open event and do related actions 
that would be normally done by the scroll handler.
+                               // If we left this to the scroll handler, the 
size of the panel would change mid-animation
+                               // and the end position would be off.
+                               panel.panelIsOpen = true;
+                               panel.$dragIcon.addClass( 'panel-open' );
+                               // use triggerHandler instead of trigger 
because it is non-async; the untruncate handler
+                               // must run before the toggle() call
+                               panel.$container.triggerHandler( 
'mmv-metadata-open' );
+
+                               panel.toggle( 'up' );
+                       } );
+
+               this.$dragIconBottom = $( '<div>' )
+                       .addClass( 'mw-mmv-drag-icon 
mw-mmv-drag-icon-pointing-up' )
+                       .prop( 'title', mw.message( 
'multimediaviewer-panel-close-popup-text' ).text() )
+                       .tipsy( { gravity: 's', delayIn: mw.config.get( 
'wgMultimediaViewer').tooltipDelay } )
+                       .appendTo( this.$container )
+                       .click( function () {
+                               panel.toggle( 'down' );
+                       } );
+
                this.hasOpenedMetadata = !this.localStorage || 
this.localStorage.getItem( 'mmv.hasOpenedMetadata' );
        };
 
@@ -186,16 +219,15 @@
        };
 
        /**
-        * Receives the window's scroll events and and turns them into business 
logic events
-        * @fires mmv-metadata-open
-        * @fires mmv-metadata-close
+        * Receives the window's scroll events and flips the chevron if 
necessary.
         */
        MPSP.scroll = function () {
                var panelIsOpen = $.scrollTo().scrollTop() > 0;
 
+               this.$dragIcon.toggleClass( 'panel-open', panelIsOpen );
                this.$container.toggleClass( 'panel-open', panelIsOpen );
 
-               if ( panelIsOpen && !this.panelIsOpen ) { // just opened
+               if ( panelIsOpen && !this.panelIsOpen ) { // just opened (this 
is skipped in some cases, see the $dragIcon click handler)
                        this.$container.trigger( 'mmv-metadata-open' );
                } else if ( !panelIsOpen && this.panelIsOpen ) { // just closed
                        this.$container.trigger( 'mmv-metadata-close' );
diff --git a/resources/mmv/ui/mmv.ui.metadataPanelScroller.less 
b/resources/mmv/ui/mmv.ui.metadataPanelScroller.less
index 8362829..39f3422 100644
--- a/resources/mmv/ui/mmv.ui.metadataPanelScroller.less
+++ b/resources/mmv/ui/mmv.ui.metadataPanelScroller.less
@@ -2,6 +2,11 @@
 @import "../mmv.mixins";
 @import "mediawiki.mixins.animation";
 
+@drag-icon-width: 64px;
+@drag-icon-height: 18px;
+@drag-icon-color: #e6e6e6;
+@drag-icon-invite-color: #347bff;
+
 .mw-mmv-post-image {
        .animation( mw-mmv-appear-animation 0.5s ease 0s 1 normal forwards );
        transition: box-shadow 0.25s;
@@ -74,3 +79,98 @@
 @keyframes mw-mmv-invite-animation {
        .mw-mmv-invite-animation;
 }
+
+.mw-mmv-drag-icon {
+       width: @drag-icon-width;
+       height: @drag-icon-height;
+
+       position: absolute;
+       left: 50%;
+       bottom: 0;
+       margin: 0 0 0 -(@drag-icon-width / 2);
+
+       /* @embed */
+       background-image: url(img/drag.svg);
+       background-repeat: no-repeat;
+       background-position: center bottom;
+       background-color: @drag-icon-color;
+
+       cursor: pointer;
+       z-index: 1; // make sure it is above the text - the icon is visually at 
the bottom but in the DOM at the top
+       .opacity(0.7);
+       transition: opacity 0.25s;
+
+       &-pointing-down { // use single-class selector - chevron direction is 
important enough to make it IE6-compatible
+               background-position: center top;
+               .rotate(180deg);
+
+               -webkit-border-bottom-left-radius: 3px;
+               -webkit-border-bottom-right-radius: 3px;
+               -moz-border-radius-bottomleft: 3px;
+               -moz-border-radius-bottomright: 3px;
+               border-bottom-left-radius: 3px;
+               border-bottom-right-radius: 3px;
+
+               .mw-mmv-post-image:hover & {
+                       .opacity(1);
+               }
+       }
+       &-pointing-up {
+               -webkit-border-top-left-radius: 3px;
+               -webkit-border-top-right-radius: 3px;
+               -moz-border-radius-topleft: 3px;
+               -moz-border-radius-topright: 3px;
+               border-top-left-radius: 3px;
+               border-top-right-radius: 3px;
+
+               &:hover {
+                       .opacity(1);
+               }
+       }
+
+       &.panel-open {
+               display: none;
+       }
+
+       &.panel-never-opened {
+               /* @embed */
+               background-image: url(img/drag-active.svg);
+               background-color: @drag-icon-invite-color;
+               .opacity(1);
+               .animation( mw-mmv-appear-chevron-animation 1.4s ease 0s 1 
normal forwards );
+       }
+
+       .jq-fullscreened & {
+               display: none;
+       }
+}
+
+.mw-mmv-appear-chevron-animation() {
+       0% {
+               opacity: 0;
+       }
+       85% {
+               opacity: 0;
+               bottom: -5px;
+       }
+       100% {
+               opacity: 1;
+               bottom: 0px;
+       }
+}
+
+@-webkit-keyframes mw-mmv-appear-chevron-animation {
+       .mw-mmv-appear-chevron-animation;
+}
+
+@-moz-keyframes mw-mmv-appear-chevron-animation {
+       .mw-mmv-appear-chevron-animation;
+}
+
+@-o-keyframes mw-mmv-appear-chevron-animation {
+       .mw-mmv-appear-chevron-animation;
+}
+
+@keyframes mw-mmv-appear-chevron-animation {
+       .mw-mmv-appear-chevron-animation;
+}
diff --git a/resources/mmv/ui/mmv.ui.stripeButtons.less 
b/resources/mmv/ui/mmv.ui.stripeButtons.less
index b422305..5cc457b 100644
--- a/resources/mmv/ui/mmv.ui.stripeButtons.less
+++ b/resources/mmv/ui/mmv.ui.stripeButtons.less
@@ -13,7 +13,18 @@
        @button-text-color: rgb(136, 136, 136);
 
        float: right;
-       margin-top: @metadatabar-above-fold-inner-height - ( @button-height + 2 
* @button-vertical-padding );
+       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;
+               }
+       }
 
        .unselectable;
        font-size: 1.25em;
@@ -45,6 +56,9 @@
        }
        &.has-label:before {
                margin-right: 0.25em;
+               .mw-mmv-untruncated & {
+                       margin-right: 0;
+               }
        }
 
        &.mw-mmv-description-page-button,
@@ -52,8 +66,7 @@
        &.mw-mmv-description-page-button:visited {
                border-radius: 4px;
                color: white;
-               padding: 7px 16px;
-               margin: 7px 10px;
+               margin: 0.5em 1em;
        }
 
        &.mw-mmv-description-page-button.mw-mmv-repo-button-commons:before {
diff --git a/tests/browser/features/support/pages/e2e_test_page.rb 
b/tests/browser/features/support/pages/e2e_test_page.rb
index 40657fd..605f9ee 100644
--- a/tests/browser/features/support/pages/e2e_test_page.rb
+++ b/tests/browser/features/support/pages/e2e_test_page.rb
@@ -22,7 +22,7 @@
 
   # Metadata elements
   span(:mmv_metadata_title, class: "mw-mmv-title")
-  a(:mmv_metadata_license, class: "mw-mmv-license")
+  a(:mmv_metadata_license, class: "mw-mmv-license cc-license")
   p(:mmv_metadata_credit, class: "mw-mmv-credit")
   span(:mmv_metadata_source, class: "mw-mmv-source")
 
diff --git a/tests/qunit/mmv/mmv.lightboxinterface.test.js 
b/tests/qunit/mmv/mmv.lightboxinterface.test.js
index 1a61748..cbbe68a 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 buttonOffset, panelBottom,
-                       oldRevealButtonsAndFadeIfNeeded,
-                       lightbox = new mw.mmv.LightboxInterface(),
+               var lightbox = new mw.mmv.LightboxInterface(),
                        viewer = new mw.mmv.MultimediaViewer(),
                        oldFnEnterFullscreen = $.fn.enterFullscreen,
-                       oldFnExitFullscreen = $.fn.exitFullscreen;
+                       oldFnExitFullscreen = $.fn.exitFullscreen,
+                       oldRevealButtonsAndFadeIfNeeded,
+                       buttonOffset;
 
                stubScrollTo();
 
@@ -186,16 +186,12 @@
 
                lightbox.buttons.revealAndFadeIfNeeded = $.noop;
 
-               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' );
+               assert.ok( !lightbox.panel.$imageMetadata.is( ':visible' ), 
'Image metadata is hidden' );
 
                // Exiting fullscreen
                lightbox.buttons.$fullscreen.click();
 
-               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.panel.$imageMetadata.is( ':visible' ), 
'Image metadata is visible' );
                assert.ok( !lightbox.isFullscreen, 'Lightbox knows that it\'s 
not in fullscreen mode' );
 
                // Unattach lightbox from document
diff --git a/tests/qunit/mmv/model/mmv.model.License.test.js 
b/tests/qunit/mmv/model/mmv.model.License.test.js
index 8f3393e..0aa59f2 100644
--- a/tests/qunit/mmv/model/mmv.model.License.test.js
+++ b/tests/qunit/mmv/model/mmv.model.License.test.js
@@ -116,20 +116,4 @@
                license = new mw.mmv.model.License( 'MIT' );
                assert.strictEqual( license.isCc(), false, 'Non-CC license with 
no internal name not recognized' );
        } );
-
-       QUnit.test( 'isPd()', 3, function( assert ) {
-               var license;
-
-               license = new mw.mmv.model.License( 'Public Domain', 'pd',
-                       'Public Domain for lack of originality' );
-               assert.strictEqual( license.isPd(), true, 'PD license 
recognized' );
-
-               license = new mw.mmv.model.License( 'CC-BY-SA-2.0', 
'cc-by-sa-2.0',
-                       'Creative Commons Attribution - ShareAlike 2.0',
-                       'http://creativecommons.org/licenses/by-sa/2.0/' );
-               assert.strictEqual( license.isPd(), false, 'Non-PD license not 
recognized' );
-
-               license = new mw.mmv.model.License( 'MIT' );
-               assert.strictEqual( license.isPd(), false, 'Non-PD license with 
no internal name not recognized' );
-       } );
 }( mediaWiki, jQuery ) );
diff --git a/tests/qunit/mmv/ui/mmv.ui.metadataPanel.test.js 
b/tests/qunit/mmv/ui/mmv.ui.metadataPanel.test.js
index 7ce613c..df4e5bf 100644
--- a/tests/qunit/mmv/ui/mmv.ui.metadataPanel.test.js
+++ b/tests/qunit/mmv/ui/mmv.ui.metadataPanel.test.js
@@ -9,7 +9,7 @@
                ],
 
                thingsShouldHaveEmptyClass = [
-                       '$licenseLi',
+                       '$license',
                        '$credit',
                        '$usernameLi',
                        '$locationLi',
@@ -127,7 +127,7 @@
                panel.setImageInfo( image, imageData, repoData, gender );
 
                assert.strictEqual( panel.$title.text(), title, 'Title is 
correctly set' );
-               assert.ok( panel.$credit.text(), 'Default credit is shown' );
+               assert.ok( panel.$credit.hasClass( 'empty' ), 'Credit is empty' 
);
                assert.strictEqual( panel.$license.prop( 'href' ), 
imageData.descriptionUrl,
                        'User is directed to file page for license information' 
);
                assert.ok( !panel.$license.prop( 'target' ), 'License 
information opens in same window' );
@@ -170,7 +170,6 @@
                var $qf = $( '#qunit-fixture' ),
                        panel = new mw.mmv.ui.MetadataPanel( $qf, $( '<div>' 
).appendTo( $qf ), window.localStorage, new mw.mmv.Config( {}, mw.config, 
mw.user, new mw.Api(), window.localStorage ) );
 
-               panel.setLicense( null, 'http://example.com' ); // make sure 
license is visible as it contains the permission
                panel.setPermission( 'Look at me, I am a permission!' );
                assert.ok( panel.$permissionLink.is( ':visible' ) );
        } );
diff --git a/tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js 
b/tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js
index 09b98a5..01b9b94 100644
--- a/tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js
+++ b/tests/qunit/mmv/ui/mmv.ui.metadataPanelScroller.test.js
@@ -146,7 +146,7 @@
                } );
        }
 
-       QUnit.test( 'Metadata scrolling', 6, function ( assert ) {
+       QUnit.test( 'Metadata scrolling', 7, function ( assert ) {
                var $qf = $( '#qunit-fixture' ),
                        $container = $( '<div>' ).css( 'height', 100 
).appendTo( $qf ),
                        $aboveFold = $( '<div>' ).css( 'height', 50 ).appendTo( 
$container ),
@@ -181,6 +181,15 @@
                assert.strictEqual( $.scrollTo().scrollTop(), 0,
                        'scrollTo scrollTop should be set to 0 after pressing 
down arrow' );
 
+               scroller.$dragIcon.click();
+               this.clock.tick( scroller.toggleScrollDuration );
+
+               scroller.$dragIconBottom.click();
+               this.clock.tick( scroller.toggleScrollDuration );
+
+               assert.strictEqual( $.scrollTo().scrollTop(), 0,
+                       'scrollTo scrollTop should be set to 0 after clicking 
the chevron twice' );
+
                // Unattach lightbox from document
                scroller.unattach();
 
@@ -205,7 +214,7 @@
                scroller.unattach();
        } );
 
-       QUnit.test( 'Metadata scroll logging', 4, function ( assert ) {
+       QUnit.test( 'Metadata scroll logging', 6, function ( assert ) {
                var $qf = $( '#qunit-fixture' ),
                        $container = $( '<div>' ).css( 'height', 100 
).appendTo( $qf ),
                        $aboveFold = $( '<div>' ).css( 'height', 50 ).appendTo( 
$container ),
@@ -243,5 +252,17 @@
 
                assert.ok( mw.mmv.actionLogger.log.calledWithExactly( 
'metadata-close' ), 'Closing keypress logged' );
                mw.mmv.actionLogger.log.reset();
+
+               scroller.$dragIcon.click();
+               this.clock.tick( scroller.toggleScrollDuration );
+
+               assert.ok( mw.mmv.actionLogger.log.calledWithExactly( 
'metadata-open' ), 'Opening click logged' );
+               mw.mmv.actionLogger.log.reset();
+
+               scroller.$dragIconBottom.click();
+               this.clock.tick( scroller.toggleScrollDuration );
+
+               assert.ok( mw.mmv.actionLogger.log.calledWithExactly( 
'metadata-close' ), 'Closing click logged' );
+               mw.mmv.actionLogger.log.reset();
        } );
 }( mediaWiki, jQuery ) );

-- 
To view, visit https://gerrit.wikimedia.org/r/170804
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I33a76ba9f9f29f9c45f46bc6c03475e0c51f2d09
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/MultimediaViewer
Gerrit-Branch: master
Gerrit-Owner: Gilles <gdu...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to