From 43d0a2454760f8cf8eae1895b9d8b86e9846b6a8 Mon Sep 17 00:00:00 2001 From: Yuki Joou Date: Thu, 3 Aug 2023 16:03:12 +0200 Subject: [PATCH] StillImage: Improved animated image detection This patch makes StillImage's animation detection return early in cases where we can't detect the mimetype of the image. It also sets the image as animated in those cases if the user agent wants reduced motion. As reduced motion is an accessibility setting, I think it's best to use a "better safe than sorry" approach, it's better to accidentally mark something as animated that isn't than to have unblocked animations. --- src/components/still-image/still-image.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/components/still-image/still-image.js b/src/components/still-image/still-image.js index 81da126a..9c335d6c 100644 --- a/src/components/still-image/still-image.js +++ b/src/components/still-image/still-image.js @@ -39,12 +39,25 @@ const StillImage = { this.imageLoadError && this.imageLoadError() }, detectAnimation (image) { + // If there are no file extensions, the mimetype isn't set, and no mediaproxy is available, we can't figure out + // the mimetype of the image. + const hasFileExtension = this.src.split('/').pop().includes('.') // TODO: Better check? + const mediaProxyAvailable = this.$store.state.instance.mediaProxyAvailable + if (!hasFileExtension && this.mimetype === undefined && !mediaProxyAvailable) { + // It's a bit aggressive to assume all images we can't find the mimetype of is animated, but necessary for + // people in need of reduced motion accessibility. As such, we'll consider those images animated if the user + // agent is set to prefer reduced motion. Otherwise, it'll just be used as an early exit. + if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) + this.isAnimated = true + return + } + if (this.mimetype === 'image/gif' || this.src.endsWith('.gif')) { this.isAnimated = true return } // harmless CORS errors without-- clean console with - if (!this.$store.state.instance.mediaProxyAvailable) return + if (!mediaProxyAvailable) return // Animated JPEGs? if (!(this.src.endsWith('.webp') || this.src.endsWith('.png'))) return // Browser Cache should ensure image doesn't get loaded twice if cache exists