Hello and welcome to the Community Forums!
That’s a known incompatibility between Extension:NSFileRepo and Extension:MultimediaViewer. Thise patches should work:
extensions/MultimediaViewer/resources/mmv.bootstrap/mmv.bootstrap.js
diff --git a/resources/mmv.bootstrap/mmv.bootstrap.js b/resources/mmv.bootstrap/mmv.bootstrap.js
index 3abb67e1..1646af24 100644
--- a/resources/mmv.bootstrap/mmv.bootstrap.js
+++ b/resources/mmv.bootstrap/mmv.bootstrap.js
@@ -276,7 +276,7 @@ class MultimediaViewerBootstrap {
// if this is a PDF filetype thumbnail, it can trick us,
// so we short-circuit that logic and use the file page title
// instead of the thumbnail logic.
- title = mw.Title.newFromText( mw.config.get( 'wgTitle' ), mw.config.get( 'wgNamespaceNumber' ) );
+ title = mw.Title.makeTitle( mw.config.get( 'wgNamespaceNumber' ), mw.config.get( 'wgTitle' ) );
} else {
title = mw.Title.newFromImg( $thumb );
}
@@ -329,7 +329,56 @@ class MultimediaViewerBootstrap {
// no longer supported
'[typeof*="mw:Image"]'
);
- const title = mw.Title.newFromImg( $thumb );
+
+ /**
+ * nsfr_img_auth.php/3000/e/ea/Image.png
+ * nsfr_img_auth.php/thumb/4/4c/Image.png/300px-Image.png
+ * nsfr_img_auth.php/thumb/archive/3000/e/ea/20250326041929!Image.png/300px-Image.png
+ */
+ const src = decodeURI( thumb.src );
+ const parts = src.split( '/' );
+
+ let title;
+ let isArchive;
+ let namespaceNumber;
+ let namespaceName;
+ let fileName;
+ let timestamp;
+
+ parts.forEach( ( part, index ) => {
+ if ( part === 'archive' ) {
+ isArchive = true;
+ } else if ( /^\d{4}$/.test( part ) ) {
+ namespaceNumber = part;
+ } else if ( part.length === 2 && parts[ index - 1 ].length === 1 ) {
+ // /e/ea/filename
+ fileName = decodeURIComponent( parts[ index + 1 ] );
+ }
+ } );
+
+ if ( isArchive && fileName && fileName.includes( '!' ) ) {
+ const archiveFileName = fileName.split( '!' );
+ timestamp = archiveFileName[ 0 ];
+ fileName = archiveFileName[ 1 ];
+ }
+
+ if ( namespaceNumber ) {
+ const formattedNamespaces = mw.config.get( 'wgFormattedNamespaces' );
+ namespaceName = formattedNamespaces[ namespaceNumber ];
+ fileName = `${ namespaceName }:${ fileName }`;
+ }
+
+ // File = 6
+ title = mw.Title.makeTitle( 6, fileName );
+
+ if ( !title ) {
+ title = mw.Title.newFromImg( $thumb );
+ }
+
+ if ( isArchive && timestamp ) {
+ title.timestamp = timestamp;
+ }
+
let caption;
if ( !this.isValidExtension( title ) ) {
extensions/MultimediaViewer/resources/mmv/provider/mmv.provider.ImageInfo.js
diff --git a/resources/mmv/provider/mmv.provider.ImageInfo.js b/resources/mmv/provider/mmv.provider.ImageInfo.js
index e8302b1f..445d071c 100644
--- a/resources/mmv/provider/mmv.provider.ImageInfo.js
+++ b/resources/mmv/provider/mmv.provider.ImageInfo.js
@@ -91,7 +91,7 @@ class ImageInfo extends Api {
* @return {jQuery.Promise} a promise which resolves to an Image object.
*/
get( file ) {
- return this.getCachedPromise( file.getPrefixedDb(), () => this.apiGetWithMaxAge( {
+ const params = {
formatversion: 2,
action: 'query',
prop: 'imageinfo',
@@ -100,7 +100,16 @@ class ImageInfo extends Api {
iiextmetadatafilter: this.iiextmetadatafilter,
iiextmetadatalanguage: this.options.language,
uselang: 'content'
- } ).then( ( data ) => this.getQueryPage( data ) ).then( ( page ) => {
+ };
+
+ if ( file.timestamp ) {
+ // To get the old image we have to reduce the timestamp and set the iistart for the imageinfo api.
+ params.iistart = file.timestamp -1;
+ }
+
+ return this.getCachedPromise( file.getPrefixedDb() + ( file.timestamp || '' ), () => this.apiGetWithMaxAge(
+ params
+ ).then( ( data ) => this.getQueryPage( data ) ).then( ( page ) => {
if ( page.imageinfo && page.imageinfo.length ) {
return ImageModel.newFromImageInfo( file, page );
} else if ( page.missing === true && page.imagerepository === '' ) {
extensions/MultimediaViewer/resources/mmv/provider/mmv.provider.ThumbnailInfo.js
diff --git a/resources/mmv/provider/mmv.provider.ThumbnailInfo.js b/resources/mmv/provider/mmv.provider.ThumbnailInfo.js
index a3d742a3..0e698376 100644
--- a/resources/mmv/provider/mmv.provider.ThumbnailInfo.js
+++ b/resources/mmv/provider/mmv.provider.ThumbnailInfo.js
@@ -50,9 +50,9 @@ class ThumbnailInfo extends Api {
get( file, sampleUrl, width, height ) {
const match = sampleUrl.match( /(lang|page)([\d\-a-z]+)-(\d+)px/ ); // multi lingual SVG or PDF page
const iiurlparam = match ? `${ match[ 1 ] }${ match[ 2 ] }-${ width }px` : undefined;
- const cacheKey = [ file.getPrefixedDb(), width || '', height || '', iiurlparam || '' ].join();
+ const cacheKey = [ file.getPrefixedDb(), width || '', height || '', iiurlparam || '', file.timestamp || '' ].join();
- return this.getCachedPromise( cacheKey, () => this.apiGetWithMaxAge( {
+ const params = {
formatversion: 2,
action: 'query',
prop: 'imageinfo',
@@ -61,7 +61,15 @@ class ThumbnailInfo extends Api {
iiurlparam,
iiurlwidth: width,
iiurlheight: height
- } ).then( ( data ) => this.getQueryPage( data ) ).then( ( page ) => {
+ };
+
+ if ( file.timestamp ) {
+ params.iistart = file.timestamp - 1;
+ }
+
+ return this.getCachedPromise( cacheKey, () => this.apiGetWithMaxAge(
+ params
+ ).then( ( data ) => this.getQueryPage( data ) ).then( ( page ) => {
let imageInfo;
if ( page.imageinfo && page.imageinfo[ 0 ] ) {
imageInfo = page.imageinfo[ 0 ];
Actually, I don’t think all of them are required for this particular case. Some may be for better support of “archived image versions” (e.g. when using Extension:FlaggedRevs or Extension:ContentStabilization)