From 70cc7945d68aadc2de62aba9441638a98145c5e9 Mon Sep 17 00:00:00 2001 From: GrosPoulet Date: Sun, 15 Dec 2024 20:51:30 +0100 Subject: [PATCH] New action key: ban an image, video or audio track A new action key (default value: "B") can be used to prevent an image, video or audio track from being zoomed (and played) next time it is hovered. Ban is not lifted by just restarting browser. So in Advanced options, a new button is available in order to reset banned items so they can be zoomed again. --- _locales/en/messages.json | 20 +++++++++++++++++ css/style.css | 5 +++-- html/options.html | 6 ++++++ js/background.js | 45 +++++++++++++++++++++++++++++++++++++++ js/common.js | 2 ++ js/hoverzoom.js | 39 ++++++++++++++++++++++++++++++++- js/options.js | 8 ++++++- js/popup.js | 2 +- 8 files changed, 122 insertions(+), 5 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index c67f456a9..f1de5277e 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -747,6 +747,18 @@ "message": "On save, replace original filename by:", "description": "[options] Replace original filename when downloading option" }, + "optResetAllBannedImagesTooltip": { + "message": "After reset, all banned images, videos & audio tracks can be zoomed again", + "description": "[options] Tooltip for reset all banned images option" + }, + "optResetAllBannedImages": { + "message": "Reset all banned images, videos & audio tracks", + "description": "[options] Reset all banned images option" + }, + "optButtonResetAllBannedImages": { + "message": "Reset", + "description": "[options] Reset all banned images button" + }, "optSectionTroubleshooting": { "message": "Troubleshooting", "description": "[options] Page section for troubleshooting" @@ -941,6 +953,14 @@ }, "optHideKeyDescription": { "message": "Holding this key down hides the zoomed image or video. Use it when the picture hides elements that are also displayed on mouseover.", + "description": "[options] Action key description" + }, + "optBanKeyTitle": { + "message": "Ban image", + "description": "[options] Action key title" + }, + "optBanKeyDescription": { + "message": "Holding this key down adds the zoomed image or video to ban list. Use it when you do not want an image or video to be zoomed again on this page.", "description": "[options] Action key description" }, "optOpenImageInWindowKeyTitle": { diff --git a/css/style.css b/css/style.css index 313121b75..f3c692258 100644 --- a/css/style.css +++ b/css/style.css @@ -92,10 +92,11 @@ body.popup.darkmode { background-color: #101010F0; } /* dark grey */ .popup.darkmode table tr:nth-child(even) { background-color: #DCB200F0; } /* yellow */ .popup table tr:nth-child(odd) { background-color: #85B7E740; } /* light blue */ .popup.darkmode table tr:nth-child(odd) { background-color: #0360B9F0; } /* blue */ -.popup table tr td { font-size: 12px; padding-left: 5px; padding-right: 5px; padding-top: 1px; padding-bottom: 1px; border-top: 0px; color: #202020F0; } +.popup table tr td { font-size: 10px; padding-left: 5px; padding-right: 5px; padding-top: 0px; padding-bottom: 0px; border: 0px; color: #202020F0; } .popup table tr td.ttip { padding-right: 30px; } -.popup .picker { height: auto; padding-right: 5px; } + +.popup .picker { height: auto; padding: 0px; font-size: 10px; margin: 0px; } .popup.darkmode .picker { background-image: linear-gradient(#606060F0, #101010F0); color: #F0F0F0F0; background-color: #101010F0; } .popup .tab-content, .popup .checkbox { padding-left: 10px; padding-right: 10px; padding-top: 0px; padding-bottom: 0px; } diff --git a/html/options.html b/html/options.html index 256401327..c68f7fe30 100644 --- a/html/options.html +++ b/html/options.html @@ -649,6 +649,12 @@

+
+
  • +
    +
    +
  • +
    diff --git a/js/background.js b/js/background.js index 6b213749e..48b5f66f8 100644 --- a/js/background.js +++ b/js/background.js @@ -206,6 +206,15 @@ function onMessage(message, sender, callback) { case 'storeHeaderSettings': storeHeaderSettings(message); return true; + case 'banImage': + banImage(message); + break; + case 'resetBannedImages': + resetBannedImages(); + break; + case 'isImageBanned': + callback(isImageBanned(message)); + return true; } } @@ -407,4 +416,40 @@ function removeWebRequestListeners() { sessionStorage.removeItem('HoverZoomHeaderSettings'); } +// add url of image, video or audio track to ban list so it will not be zoomed again +function banImage(message) { + const url = message.url; + + // store urls to ban in background page local storage so theys are shared by all pages & will survive browser restart + let bannedUrls = localStorage.getItem('HoverZoomBannedUrls') || '{}'; + try { + let update = false; + bannedUrls = JSON.parse(bannedUrls); + if (url && !bannedUrls[url]) { + bannedUrls[url] = { 'location' : message.location }; + update = true; + } + if (update) localStorage.setItem('HoverZoomBannedUrls', JSON.stringify(bannedUrls)); + } catch {} +} + +// clear list of banned image, video or audio track urls +function resetBannedImages() { + localStorage.removeItem('HoverZoomBannedUrls'); +} + +// check if url of image, video or audio track belongs to ban list +function isImageBanned(message) { + const url = message.url; + let bannedUrls = localStorage.getItem('HoverZoomBannedUrls') || '{}'; + try { + bannedUrls = JSON.parse(bannedUrls); + } catch { return false; } + if (!bannedUrls[url]) { + return false; + } else { + return true; + } +} + init(); diff --git a/js/common.js b/js/common.js index 46476fcc4..d9d74dcd4 100644 --- a/js/common.js +++ b/js/common.js @@ -84,6 +84,7 @@ var factorySettings = { copyImageKey: 67, copyImageUrlKey: 85, hideKey : 88, + banKey : 66, openImageInWindowKey : 87, openImageInTabKey : 84, lockImageKey : 76, @@ -205,6 +206,7 @@ function loadOptions() { options.copyImageKey = options.hasOwnProperty('copyImageKey') ? options.copyImageKey : factorySettings.copyImageKey; options.copyImageUrlKey = options.hasOwnProperty('copyImageUrlKey') ? options.copyImageUrlKey : factorySettings.copyImageUrlKey; options.hideKey = options.hasOwnProperty('hideKey') ? options.hideKey : factorySettings.hideKey; + options.banKey = options.hasOwnProperty('banKey') ? options.banKey : factorySettings.banKey; options.openImageInWindowKey = options.hasOwnProperty('openImageInWindowKey') ? options.openImageInWindowKey : factorySettings.openImageInWindowKey; options.openImageInTabKey = options.hasOwnProperty('openImageInTabKey') ? options.openImageInTabKey : factorySettings.openImageInTabKey; options.lockImageKey = options.hasOwnProperty('lockImageKey') ? options.lockImageKey : factorySettings.lockImageKey; diff --git a/js/hoverzoom.js b/js/hoverzoom.js index cc60a22cc..422e00b2c 100644 --- a/js/hoverzoom.js +++ b/js/hoverzoom.js @@ -1070,7 +1070,20 @@ var hoverZoom = { // if the action key has been pressed over an image, no delay is applied const delay = actionKeyDown || explicitCall ? 0 : (isVideoLink(srcDetails.url) ? options.displayDelayVideo : options.displayDelay); - loadFullSizeImageTimeout = setTimeout(loadFullSizeImage, delay); + + if (audioSrc) { + chrome.runtime.sendMessage({action:'isImageBanned', url:audioSrc}, function (result) { + if (!result) { + loadFullSizeImageTimeout = setTimeout(loadFullSizeImage, delay); + } + }); + } else if (src) { + chrome.runtime.sendMessage({action:'isImageBanned', url:src}, function (result) { + if (!result) { + loadFullSizeImageTimeout = setTimeout(loadFullSizeImage, delay); + } + }); + } loading = true; } @@ -2856,6 +2869,21 @@ var hoverZoom = { return returnStatement; } + // ban key (close zoomed image + add to page's ban list) is pressed down + // => zoomed image is closed immediately + // => zoomed image url is added to page's ban list + if (event.which == options.banKey) { + hz.hzViewerLocked = viewerLocked = false; + if (hz.hzViewer) { + stopMedias(); + hz.hzViewer.hide(); + banImage(); + } + if (imgFullSize) { + return false; + } + } + // the following keys are processed only if an image is displayed if (imgFullSize) { // Cancels event if an action key is held down (auto-repeat may trigger additional events) @@ -3586,6 +3614,15 @@ var hoverZoom = { } } + // store url(s) of image, video or audio track that should not be zoomed again + function banImage() { + if (srcDetails.audioUrl) { + chrome.runtime.sendMessage({action:'banImage', url:srcDetails.audioUrl, location:window.location.href}); + } else if (srcDetails.url) { + chrome.runtime.sendMessage({action:'banImage', url:srcDetails.url, location:window.location.href}); + } + } + function saveImage() { saveImg(); saveVideo(); diff --git a/js/options.js b/js/options.js index 86960a6ee..46b280e65 100644 --- a/js/options.js +++ b/js/options.js @@ -2,7 +2,7 @@ var options, hoverZoomPlugins = hoverZoomPlugins || [], VK_CTRL = 1024, VK_SHIFT = 2048, - actionKeys = ['actionKey', 'toggleKey', 'closeKey', 'hideKey', 'openImageInWindowKey', 'openImageInTabKey', 'lockImageKey', 'saveImageKey', 'fullZoomKey', 'prevImgKey', 'nextImgKey', 'flipImageKey', 'copyImageKey', 'copyImageUrlKey']; + actionKeys = ['actionKey', 'toggleKey', 'closeKey', 'hideKey', 'banKey', 'openImageInWindowKey', 'openImageInTabKey', 'lockImageKey', 'saveImageKey', 'fullZoomKey', 'prevImgKey', 'nextImgKey', 'flipImageKey', 'copyImageKey', 'copyImageUrlKey']; function getMilliseconds(ctrl) { var value = parseFloat(ctrl.val()); @@ -578,6 +578,11 @@ function replaceOriginalFilenameOnChange(val) { return this.value; } +function btnResetAllBannedImagesOnClick() { + const request = {action:'resetBannedImages'}; + chrome.runtime.sendMessage(request); +} + function updateDivAmbilight() { if ($('#chkAmbilightEnabled')[0].checked) { $('#divAmbilight').removeClass('disabled'); @@ -844,6 +849,7 @@ $(function () { $('#txtDownloadFolder').change(downloadFolderOnChange); $('#chkDownloadReplaceOriginalFilename').parent().on('gumby.onChange', updateDownloadReplaceOriginalFilename); $('#txtDownloadReplaceOriginalFilename').change(replaceOriginalFilenameOnChange); + $('#btnResetAllBannedImages').click(btnResetAllBannedImagesOnClick); $('#chkUseSeparateTabOrWindowForUnloadableUrlsEnabled').parent().on('gumby.onChange', updateUseSeparateTabOrWindowForUnloadableUrls); $('#chkHideMouseCursor').parent().on('gumby.onChange', updateDivHideMouseCursor); $('#chkDarkMode').parent().on('gumby.onChange', updateDarkMode); diff --git a/js/popup.js b/js/popup.js index fdbcfd8da..7545e28fa 100644 --- a/js/popup.js +++ b/js/popup.js @@ -3,7 +3,7 @@ var options, prgPreloading, lblPreloading, aPreload, VK_CTRL = 1024, VK_SHIFT = 2048, - actionKeys = ['actionKey', 'toggleKey', 'closeKey', 'hideKey', 'openImageInWindowKey', 'openImageInTabKey', 'lockImageKey', 'saveImageKey', 'fullZoomKey', 'prevImgKey', 'nextImgKey', 'flipImageKey', 'copyImageKey', 'copyImageUrlKey']; + actionKeys = ['actionKey', 'toggleKey', 'closeKey', 'hideKey', 'banKey', 'openImageInWindowKey', 'openImageInTabKey', 'lockImageKey', 'saveImageKey', 'fullZoomKey', 'prevImgKey', 'nextImgKey', 'flipImageKey', 'copyImageKey', 'copyImageUrlKey']; function keyCodeToString(key) { var s = '';