From 1716c1486f4dbe334fb77baaca15e8bdbcd5e062 Mon Sep 17 00:00:00 2001 From: Jaifroid Date: Thu, 2 Jun 2022 18:55:32 +0100 Subject: [PATCH] * Refactor image display and intelligently turn off manipulation Former-commit-id: 0795327aae5a297607b395d15cefb0a193a8f325 [formerly e6c7358c48e984eccfa2b4e564170be66624df93 [formerly 08845f715dd25ae2d6f1b52298550c9174a60bb9]] Former-commit-id: a693defc1ce66c9ecd4fbe3da4782734db95f944 [formerly a300360422f13db877daca4e6b7833af22531b2d] Former-commit-id: 472cd9ea62dd5065b73c495b9ac1ec0310572662 --- service-worker.js | 4 +-- www/js/app.js | 58 +++++++++++++++++++++++++++--------- www/js/init.js | 2 +- www/js/lib/images.js | 10 ++++--- www/js/lib/transformZimit.js | 9 ++---- 5 files changed, 56 insertions(+), 27 deletions(-) diff --git a/service-worker.js b/service-worker.js index bb392f44..0340d3a3 100644 --- a/service-worker.js +++ b/service-worker.js @@ -295,9 +295,9 @@ self.addEventListener('fetch', function (event) { // The response was not found in the cache so we look for it in the ZIM // and add it to the cache if it is an asset type (css or js) if (cache === ASSETS_CACHE && regexpZIMUrlWithNamespace.test(strippedUrl)) { - if (imageDisplay !== 'all' && /\/.*\.(jpe?g|png|svg|gif|webp)(?!.*?kiwix-display)/i.test(rqUrl)) { + if (imageDisplay !== 'all' && /\/.*\.(jpe?g|png|svg|gif|webp)(?=.*?kiwix-display)/i.test(rqUrl)) { // If the user has disabled the display of images, and the browser wants an image, respond with empty SVG - // A URL with "?kiwix-display" query string acts as a passthrough so that the regex will not match and + // A URL without "?kiwix-display" query string acts as a passthrough so that the regex will not match and // the image will be fetched by app.js // DEV: If you need to hide more image types, add them to regex below and also edit equivalent regex in app.js var svgResponse; diff --git a/www/js/app.js b/www/js/app.js index 6f989522..7ba1fb44 100644 --- a/www/js/app.js +++ b/www/js/app.js @@ -1137,14 +1137,17 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images ); } if (this.value === 'serviceworker') { + var wikimediaZimLoaded = appstate.selectedArchive && /wikipedia|wikivoyage|mdwiki|wiktionary/i.test(appstate.selectedArchive._file.name); if (params.displayHiddenBlockElements || params.manipulateImages || params.allowHTMLExtraction) { - uiUtil.systemAlert( + if (!wikimediaZimLoaded) uiUtil.systemAlert( 'Please note that we are disabling Image manipulation, Breakout link and/or Display hidden block elements, as these options can interfere with ZIMs that have active content. You may turn them back on, but be aware that they are only recommended for use with Wikimedia ZIMs.' ); } - if (params.manipulateImages) document.getElementById('manipulateImagesCheck').click(); - if (params.displayHiddenBlockElements) document.getElementById('displayHiddenBlockElementsCheck').click(); - if (params.allowHTMLExtraction) document.getElementById('allowHTMLExtractionCheck').click(); + if (!wikimediaZimLoaded) { + if (params.manipulateImages) document.getElementById('manipulateImagesCheck').click(); + if (params.displayHiddenBlockElements) document.getElementById('displayHiddenBlockElementsCheck').click(); + if (params.allowHTMLExtraction) document.getElementById('allowHTMLExtractionCheck').click(); + } } params.themeChanged = true; // This will reload the page }); @@ -1204,6 +1207,11 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images uiUtil.systemAlert('This setting will be applied on next app launch'); }); $('input:checkbox[name=imageDisplayMode]').on('change', function (e) { + if (params.contentInjectionMode === 'serviceworker' && !this.checked) { + uiUtil.systemAlert('Image display can only be turned off in JQuery mode!'); + this.checked = true; + return; + } params.imageDisplay = this.checked ? true : false; params.imageDisplayMode = this.checked ? 'progressive' : 'manual'; params.themeChanged = params.imageDisplay; //Only reload page if user asked for all images to be displayed @@ -1219,7 +1227,8 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images '

You will then be able to right-click or long-press images in the exported page and save them.

'); } else if (window.nw) { uiUtil.systemAlert('Unfortunately there is currently no way to save an image to disk in the NWJS version of this app.
You can do this in the PWA version: please visit https://pwa.kiwix.org.'); - } else if (params.contentInjectionMode === 'serviceworker') { + } else if (params.contentInjectionMode === 'serviceworker' && appstate.selectedArchive + && !/wikimedia|wikivoyage|mdwiki|wiktionary/i.test(appstate.selectedArchive._file.name)) { uiUtil.systemAlert('Please be aware that Image manipulation can interfere with non-Wikimedia ZIMs (particularly ZIMs that have active content). If you cannot access the articles in such a ZIM, please turn this setting off.'); } else if (/PWA/.test(params.appType)) { uiUtil.systemAlert('Be aware that this option may interfere with active content if you switch to Service Worker mode.'); @@ -2572,7 +2581,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images readNodeDirectoryAndCreateNodeFileObjects(params.pickedFolder, archive) .then(function (fileset) { var selectedFiles = fileset[0]; - if (appstate.selectArchive && appstate.selectArchive._file.files[0].name === selectedFiles[0].name) return; + if (appstate.selectedArchive && appstate.selectedArchive._file.files[0].name === selectedFiles[0].name) return; setLocalArchiveFromFileList(selectedFiles); }); } else { @@ -2626,6 +2635,14 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images // Ensure that the new ZIM output is initially sent to the iframe (e.g. if the last article was loaded in a window) // (this only affects jQuery mode) appstate.target = 'iframe'; + if (params.contentInjectionMode === 'serviceworker') { + var wikimediaZimLoaded = appstate.selectedArchive && /wikipedia|wikivoyage|mdwiki|wiktionary/i.test(appstate.selectedArchive._file.name); + if (!wikimediaZimLoaded) { + if (params.manipulateImages) document.getElementById('manipulateImagesCheck').click(); + if (params.displayHiddenBlockElements) document.getElementById('displayHiddenBlockElementsCheck').click(); + if (params.allowHTMLExtraction) document.getElementById('allowHTMLExtractionCheck').click(); + } + } // The archive is set : go back to home page to start searching if (params.rescan) { document.getElementById('btnConfigure').click(); @@ -2980,6 +2997,14 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images // (this only affects jQuery mode) appstate.target = 'iframe'; // The archive is set : go back to home page to start searching + if (params.contentInjectionMode === 'serviceworker') { + var wikimediaZimLoaded = appstate.selectedArchive && /wikipedia|wikivoyage|mdwiki|wiktionary/i.test(appstate.selectedArchive._file.name); + if (!wikimediaZimLoaded) { + if (params.manipulateImages) document.getElementById('manipulateImagesCheck').click(); + if (params.displayHiddenBlockElements) document.getElementById('displayHiddenBlockElementsCheck').click(); + if (params.allowHTMLExtraction) document.getElementById('allowHTMLExtractionCheck').click(); + } + } params.storedFile = archive._file._files[0].name; settingsStore.setItem("lastSelectedArchive", params.storedFile, Infinity); settingsStore.setItem("lastSelectedArchivePath", archive._file._files[0].path ? archive._file._files[0].path : '', Infinity); @@ -3689,7 +3714,7 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images if (params.windowOpener) setTimeout(function () { parseAnchorsJQuery(dirEntry); }, 1500); - if (/manual|progressive/.test(params.imageDisplayMode)) images.prepareImagesServiceWorker(articleWindow); + if (params.manipulateImages && /manual|progressive/.test(params.imageDisplayMode)) images.prepareImagesServiceWorker(articleWindow); if (params.allowHTMLExtraction && appstate.target === 'iframe') { var determinedTheme = params.cssTheme == 'auto' ? cssUIThemeGetOrSet('auto') : params.cssTheme; uiUtil.insertBreakoutLink(determinedTheme); @@ -4073,15 +4098,20 @@ define(['jquery', 'zimArchiveLoader', 'uiUtil', 'util', 'utf8', 'cache', 'images htmlArticle = htmlArticle.replace(/(<(audio|video)\b(?:[^<]|<(?!\/\2))+<\/\2>)/ig, function (p0) { return /(?:src|data-kiwixurl)\s*=\s*["']/.test(p0) ? p0 : ''; }); - } else if (wikiLang) { + } else if (wikiLang || params.manipulateImages) { htmlArticle = htmlArticle.replace(params.regexpTagsWithZimUrl, function(match, blockStart, equals, quote, relAssetUrl, blockClose) { newBlock = match; - // For Wikipedia archives, hyperlink the image to the File version - var assetZIMUrl = decodeURIComponent(relAssetUrl); - if (/^' + newBlock + '' + // Add the kiwix-display directive so that the SW sends a dummy image instead + if (params.manipulateImages && params.imageDisplay !== 'all' && /^' + newBlock + '' + } } return newBlock; }); diff --git a/www/js/init.js b/www/js/init.js index 0f98a51c..e17ea78f 100644 --- a/www/js/init.js +++ b/www/js/init.js @@ -84,7 +84,7 @@ params['cssTheme'] = getSetting('cssTheme') || 'light'; //Set default to 'auto', params['cssUITheme'] = getSetting('cssUITheme') || 'light'; //Set default to 'auto', 'light' or 'dark' to use respective themes for UI' params['resetDisplayOnResize'] = getSetting('resetDisplayOnResize') != null ? getSetting('resetDisplayOnResize') : false; // Default for the display reset feature that fixes bugs with secondary displays params['imageDisplay'] = getSetting('imageDisplay') != null ? getSetting('imageDisplay') : true; //Set default to display images from Zim -params['manipulateImages'] = getSetting('manipulateImages') != null ? getSetting('manipulateImages') : false; //Makes dataURIs by default instead of BLOB URIs for images +params['manipulateImages'] = getSetting('manipulateImages') != null ? getSetting('manipulateImages') : true; //Makes dataURIs by default instead of BLOB URIs for images params['linkToWikimediaImageFile'] = getSetting('linkToWikimediaImageFile') != null ? getSetting('linkToWikimediaImageFile') : false; //Links images to Wikimedia online version if ZIM archive is a Wikipedia archive params['hideToolbars'] = getSetting('hideToolbars') != null ? getSetting('hideToolbars') : true; //Set default to true (hides both), 'top' (hides top only), or false (no hiding) params['rememberLastPage'] = getSetting('rememberLastPage') != null ? getSetting('rememberLastPage') : true; //Set default option to remember the last visited page between sessions diff --git a/www/js/lib/images.js b/www/js/lib/images.js index 7b705ae9..f5238fe5 100644 --- a/www/js/lib/images.js +++ b/www/js/lib/images.js @@ -82,12 +82,14 @@ define(['uiUtil'], function (uiUtil) { return; } if (params.contentInjectionMode === 'serviceworker' && !(params.manipulateImages || params.allowHTMLExtraction)) { - image.addEventListener('load', function () { + var transition = function () { image.style.transition = 'opacity 0.5s ease-in'; image.style.opacity = '1'; - }); - // Let's add kiwix-display to the end of the url so that the SW will ask for the image - image.src = imageUrl + '?kiwix-display'; + removeEventListener('load', transition); + } + image.addEventListener('load', transition); + // Let's remove kiwix-display from the end of the url so that the SW will ask for the image + image.src = imageUrl.replace(/\?kiwix-display/, ''); // Timeout allows the loop to complete so we get an accurate busy count setTimeout(function () { checkBatch(); diff --git a/www/js/lib/transformZimit.js b/www/js/lib/transformZimit.js index dbae3a98..621404c7 100644 --- a/www/js/lib/transformZimit.js +++ b/www/js/lib/transformZimit.js @@ -118,8 +118,6 @@ define([], function () { /^\//.test(assetUrl) ? assetUrl.replace(/^\//, '/' + dirEntry.namespace + '/' + params.zimitPrefix + '/') : assetUrl; // Deal with directives if (/]+refresh\b/i.test(newBlock)) dirEntry.zimitRedirect = assetUrl.replace(/^\//, ''); - // Disable lazy loading of images even if manipulateImages is off - if (/