|
// ==UserScript== |
|
// @name Derpi Show |
|
// @namespace Violentmonkey scripts |
|
// @version 2.3.0 |
|
// @author Angius |
|
// @description Derpibooru slideshow viewer |
|
// @match https://derpibooru.org/images/* |
|
// @match https://ponerpics.org/images/* |
|
// @match https://ponybooru.org/images/* |
|
// @match https://twibooru.org/images/* |
|
// @match https://manebooru.art/images/* |
|
// @match https://furbooru.org/images/* |
|
// @require https://vanjs.org/code/van-1.6.0.nomodule.min.js |
|
// @grant GM_addStyle |
|
// @grant GM_getValue |
|
// @grant GM_setValue |
|
// @top-level-await |
|
// ==/UserScript== |
|
var derpi_show_default = `[derpi-show-active="true"] { |
|
#content { |
|
position: fixed; |
|
inset: 0; |
|
padding: 0; |
|
margin: 0; |
|
background-color: oklch(0.19 0.002 285); |
|
|
|
> .block { |
|
background-color: transparent; |
|
position: fixed; |
|
top: 0; |
|
left: 0; |
|
} |
|
|
|
.image-metabar { |
|
background-color: transparent; |
|
opacity: 0.5; |
|
|
|
&:hover { |
|
opacity: 0.9; |
|
} |
|
|
|
div:not(:nth-of-type(2)) { |
|
display: none; |
|
} |
|
|
|
[class*="interaction--"] { |
|
background-color: transparent; |
|
} |
|
|
|
.interaction--comments, |
|
.interaction--hide { |
|
display: none; |
|
} |
|
} |
|
|
|
#extrameta { |
|
display: none; |
|
} |
|
|
|
.center--layout--flex { |
|
height: 100vh; |
|
width: 100vw; |
|
align-content: center; |
|
align-items: center; |
|
justify-items: center; |
|
display: flex; |
|
justify-content: center; |
|
margin-left: calc(var(--normal-margin) * -1); |
|
|
|
.image-show-container { |
|
box-shadow: 0 0 5rem black; |
|
padding: 0; |
|
} |
|
|
|
.image-scaled { |
|
max-height: 100vh; |
|
} |
|
} |
|
} |
|
} |
|
|
|
#derpi-show-btn { |
|
position: fixed; |
|
bottom: 10px; |
|
right: 10px; |
|
z-index: 10000; |
|
border: var(--border); |
|
background-color: var(--block-header-color); |
|
border-radius: 500rem; |
|
aspect-ratio: 1 / 1; |
|
color: var(--foreground-color); |
|
display: flex; |
|
padding: 0.25rem; |
|
cursor: pointer; |
|
|
|
&:hover { |
|
background-color: var(--block-header-hover-color); |
|
} |
|
|
|
svg { |
|
width: 24px; |
|
height: 24px; |
|
} |
|
} |
|
`; |
|
|
|
var hotkeys = (on) => { |
|
const handlers = []; |
|
const conditions = []; |
|
return { |
|
when(condition) { |
|
conditions.push(condition); |
|
return this; |
|
}, |
|
add(keys, handler) { |
|
handlers.push({ keys, handler }); |
|
return this; |
|
}, |
|
handle() { |
|
const flat = handlers.reduce((acc, curr) => { |
|
for (const key of curr.keys) { |
|
acc.set(key, curr.handler); |
|
} |
|
return acc; |
|
}, new Map); |
|
const listener = async (e) => { |
|
if (!(e instanceof KeyboardEvent)) { |
|
return; |
|
} |
|
if (!conditions.some((c) => c())) { |
|
return; |
|
} |
|
const handler = flat.get(e.key); |
|
if (!handler) { |
|
return; |
|
} |
|
await handler(e); |
|
}; |
|
window.addEventListener(on, listener); |
|
return () => window.removeEventListener(on, listener); |
|
} |
|
}; |
|
}; |
|
|
|
var rolling = (items) => { |
|
if (items.length === 0) { |
|
throw Error("Rolling collection cannot be empty"); |
|
} |
|
let index = 0; |
|
const n = items.length; |
|
return { |
|
next() { |
|
index = (index + 1) % n; |
|
return items[index]; |
|
}, |
|
prev() { |
|
index = (index - 1 + n) % n; |
|
return items[index]; |
|
}, |
|
current() { |
|
return items[index]; |
|
} |
|
}; |
|
}; |
|
|
|
var slideshow_default = '<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24"><!-- Icon from Remix Icon by Remix Design - https://github.com/Remix-Design/RemixIcon/blob/master/License --><path fill="currentColor" d="M13 17v3h5v2H6v-2h5v-3H4a1 1 0 0 1-1-1V4H2V2h20v2h-1v12a1 1 0 0 1-1 1zm-8-2h14V4H5zm5-9l5 3.5l-5 3.5z"/></svg>'; |
|
|
|
GM_addStyle(derpi_show_default); |
|
var { button, link } = van.tags; |
|
var isActive = van.state(GM_getValue("derpi-show-active")); |
|
document.documentElement.setAttribute("derpi-show-active", String(isActive.val)); |
|
van.derive(() => { |
|
console.log(`Derpi Show is ${isActive.val ? "active" : "inactive"}`); |
|
GM_setValue("derpi-show-active", isActive.val); |
|
document.documentElement.setAttribute("derpi-show-active", String(isActive.val)); |
|
}); |
|
var toggleBtn = button({ |
|
id: "derpi-show-btn", |
|
innerHTML: slideshow_default, |
|
onclick: () => isActive.val = !isActive.val |
|
}); |
|
van.add(document.body, toggleBtn); |
|
var preload = (url) => { |
|
if (!url) { |
|
return; |
|
} |
|
const el = link({ |
|
rel: "prefetch", |
|
href: url, |
|
fetchPriority: "auto", |
|
as: "document" |
|
}); |
|
van.add(document.head, el); |
|
}; |
|
var prev = document.querySelector("a.js-prev[href]"); |
|
var next = document.querySelector("a.js-next[href]"); |
|
if (prev) { |
|
preload(prev.href); |
|
} |
|
if (next) { |
|
preload(next.href); |
|
} |
|
var withPlayer = (func) => { |
|
const vid = document.querySelector(".image-target video"); |
|
if (vid) { |
|
return func(vid); |
|
} |
|
}; |
|
var backgrounds = rolling(["transparent", "black", "white"]); |
|
hotkeys("keyup").when(() => isActive.val).add(["a", "ArrowLeft"], () => { |
|
preload(prev?.href); |
|
prev?.click(); |
|
}).add(["d", "ArrowRight"], () => { |
|
preload(next?.href); |
|
next?.click(); |
|
}).add(["Escape"], () => { |
|
isActive.val = false; |
|
}).add(["v"], () => { |
|
const img = document.querySelector("img#image-display"); |
|
if (!img) |
|
return; |
|
img.style.backgroundColor = backgrounds.next(); |
|
}).add([" "], (e) => { |
|
e.preventDefault(); |
|
withPlayer(async (vid) => { |
|
if (vid.paused) { |
|
await vid.play(); |
|
} else { |
|
vid.pause(); |
|
} |
|
}); |
|
}).add([","], () => withPlayer((vid) => { |
|
vid.currentTime = vid.currentTime - Math.min(vid.currentTime / 10, 5); |
|
})).add(["."], () => withPlayer((vid) => { |
|
vid.currentTime = vid.currentTime + Math.min(vid.currentTime / 10, 5); |
|
})).add(["m"], () => withPlayer((vid) => { |
|
vid.muted = !vid.muted; |
|
})).add(["Enter"], (e) => withPlayer(async (vid) => { |
|
if (!e.altKey) { |
|
return; |
|
} |
|
await vid.requestFullscreen(); |
|
})).handle(); |