mirror of
https://github.com/LalleSX/4chan-XZ.git
synced 2025-10-07 07:22:37 +02:00
193 lines
4.8 KiB
JavaScript
193 lines
4.8 KiB
JavaScript
import Callbacks from '../classes/Callbacks'
|
|
import Header from '../General/Header'
|
|
import { Conf, d,g } from '../globals/globals'
|
|
import $ from '../platform/$'
|
|
|
|
/*
|
|
* decaffeinate suggestions:
|
|
* DS101: Remove unnecessary use of Array.from
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
|
|
*/
|
|
const ImageLoader = {
|
|
init() {
|
|
if (!['index', 'thread', 'archive'].includes(g.VIEW)) {
|
|
return
|
|
}
|
|
const replace =
|
|
Conf['Replace JPG'] ||
|
|
Conf['Replace PNG'] ||
|
|
Conf['Replace GIF'] ||
|
|
Conf['Replace WEBM']
|
|
if (!Conf['Image Prefetching'] && !replace) {
|
|
return
|
|
}
|
|
|
|
Callbacks.Post.push({
|
|
name: 'Image Replace',
|
|
cb: this.node,
|
|
})
|
|
|
|
$.on(d, 'PostsInserted', function () {
|
|
if (ImageLoader.prefetchEnabled || replace) {
|
|
return g.posts.forEach(ImageLoader.prefetchAll)
|
|
}
|
|
})
|
|
|
|
if (Conf['Replace WEBM']) {
|
|
$.on(
|
|
d,
|
|
'scroll visibilitychange 4chanXInitFinished PostsInserted',
|
|
this.playVideos
|
|
)
|
|
}
|
|
|
|
if (!Conf['Image Prefetching'] || !['index', 'thread'].includes(g.VIEW)) {
|
|
return
|
|
}
|
|
|
|
const el = $.el('a', {
|
|
href: 'javascript:;',
|
|
title: 'Prefetch Images',
|
|
className: 'fa fa-bolt disabled',
|
|
textContent: 'Prefetch',
|
|
})
|
|
|
|
$.on(el, 'click', this.toggle)
|
|
|
|
return Header.addShortcut('prefetch', el, 525)
|
|
},
|
|
|
|
node() {
|
|
if (this.isClone) {
|
|
return
|
|
}
|
|
for (var file of this.files) {
|
|
if (Conf['Replace WEBM'] && file.isVideo) {
|
|
ImageLoader.replaceVideo(this, file)
|
|
}
|
|
ImageLoader.prefetch(this, file)
|
|
}
|
|
},
|
|
|
|
replaceVideo(post, file) {
|
|
const { thumb } = file
|
|
const video = $.el('video', {
|
|
preload: 'none',
|
|
loop: true,
|
|
muted: true,
|
|
poster: thumb.src || thumb.dataset.src,
|
|
textContent: thumb.alt,
|
|
className: thumb.className,
|
|
})
|
|
video.setAttribute('muted', 'muted')
|
|
video.dataset.md5 = thumb.dataset.md5
|
|
for (var attr of ['height', 'width', 'maxHeight', 'maxWidth']) {
|
|
video.style[attr] = thumb.style[attr]
|
|
}
|
|
video.src = file.url
|
|
$.replace(thumb, video)
|
|
file.thumb = video
|
|
return (file.videoThumb = true)
|
|
},
|
|
|
|
prefetch(post, file) {
|
|
let clone, type
|
|
const { isImage, isVideo, thumb, url } = file
|
|
if (
|
|
file.isPrefetched ||
|
|
!(isImage || isVideo) ||
|
|
post.isHidden ||
|
|
post.thread.isHidden
|
|
) {
|
|
return
|
|
}
|
|
if (isVideo) {
|
|
type = 'WEBM'
|
|
} else {
|
|
type = url.match(/\.([^.]+)$/)?.[1].toUpperCase()
|
|
if (type === 'JPEG') {
|
|
type = 'JPG'
|
|
}
|
|
}
|
|
const replace =
|
|
Conf[`Replace ${type}`] && !/spoiler/.test(thumb.src || thumb.dataset.src)
|
|
if (!replace && !ImageLoader.prefetchEnabled) {
|
|
return
|
|
}
|
|
if ($.hasClass(d, 'catalog-mode')) {
|
|
return
|
|
}
|
|
if (
|
|
![post, ...Array.from(post.clones)].some(clone =>
|
|
d.contains(clone.nodes.root)
|
|
)
|
|
) {
|
|
return
|
|
}
|
|
file.isPrefetched = true
|
|
if (file.videoThumb) {
|
|
for (clone of post.clones) {
|
|
clone.file.thumb.preload = 'auto'
|
|
}
|
|
thumb.preload = 'auto'
|
|
// XXX Cloned video elements with poster in Firefox cause momentary display of image loading icon.
|
|
if ($.engine === 'gecko') {
|
|
$.on(thumb, 'loadeddata', function () {
|
|
return this.removeAttribute('poster')
|
|
})
|
|
}
|
|
return
|
|
}
|
|
|
|
const el = $.el(isImage ? 'img' : 'video')
|
|
if (isVideo) {
|
|
el.preload = 'auto'
|
|
}
|
|
if (replace && isImage) {
|
|
$.on(el, 'load', function () {
|
|
for (clone of post.clones) {
|
|
clone.file.thumb.src = url
|
|
}
|
|
return (thumb.src = url)
|
|
})
|
|
}
|
|
return (el.src = url)
|
|
},
|
|
|
|
prefetchAll(post) {
|
|
for (var file of post.files) {
|
|
ImageLoader.prefetch(post, file)
|
|
}
|
|
},
|
|
|
|
toggle() {
|
|
ImageLoader.prefetchEnabled = !ImageLoader.prefetchEnabled
|
|
this.classList.toggle('disabled', !ImageLoader.prefetchEnabled)
|
|
if (ImageLoader.prefetchEnabled) {
|
|
g.posts.forEach(ImageLoader.prefetchAll)
|
|
}
|
|
},
|
|
|
|
playVideos() {
|
|
// Special case: Quote previews are off screen when inserted into document, but quickly moved on screen.
|
|
const qpClone = $.id('qp')?.firstElementChild
|
|
return g.posts.forEach(function (post) {
|
|
for (post of [post, ...Array.from(post.clones)]) {
|
|
for (var file of post.files) {
|
|
if (file.isVideo && !file.isPrefetched) {
|
|
const { thumb } = file
|
|
if (qpClone === thumb) {
|
|
continue
|
|
}
|
|
if (thumb.getBoundingClientRect().top < window.innerHeight) {
|
|
ImageLoader.prefetch(post, file)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
},
|
|
}
|
|
export default ImageLoader
|