// ==UserScript==
// @name r34app gallery
// @description Gallery view for results in https://r34.app
// @locale en
// @namespace r34app-gallery
// @version 1.3.0
// @require https://cdnjs.cloudflare.com/ajax/libs/jquery/1.9.1/jquery.min.js
// @require https://cdnjs.cloudflare.com/ajax/libs/magnific-popup.js/1.1.0/jquery.magnific-popup.min.js
// @include https://r34.app/*
// ==/UserScript==
const styles = `
.mfp-bg{top:0;left:0;width:100%;height:100%;z-index:1042;overflow:hidden;position:fixed;background:#0b0b0b;opacity:.8}.mfp-wrap{top:0;left:0;width:100%;height:100%;z-index:1043;position:fixed;outline:none !important;-webkit-backface-visibility:hidden}.mfp-container{text-align:center;position:absolute;width:100%;height:100%;left:0;top:0;padding:0 8px;box-sizing:border-box}.mfp-container:before{content:'';display:inline-block;height:100%;vertical-align:middle}.mfp-align-top .mfp-container:before{display:none}.mfp-content{position:relative;display:inline-block;vertical-align:middle;margin:0 auto;text-align:left;z-index:1045}.mfp-inline-holder .mfp-content,.mfp-ajax-holder .mfp-content{width:100%;cursor:auto}.mfp-ajax-cur{cursor:progress}.mfp-zoom-out-cur,.mfp-zoom-out-cur .mfp-image-holder .mfp-close{cursor:-moz-zoom-out;cursor:-webkit-zoom-out;cursor:zoom-out}.mfp-zoom{cursor:pointer;cursor:-webkit-zoom-in;cursor:-moz-zoom-in;cursor:zoom-in}.mfp-auto-cursor .mfp-content{cursor:auto}.mfp-close,.mfp-arrow,.mfp-preloader,.mfp-counter{-webkit-user-select:none;-moz-user-select:none;user-select:none}.mfp-loading.mfp-figure{display:none}.mfp-hide{display:none !important}.mfp-preloader{color:#CCC;position:absolute;top:50%;width:auto;text-align:center;margin-top:-0.8em;left:8px;right:8px;z-index:1044}.mfp-preloader a{color:#CCC}.mfp-preloader a:hover{color:#FFF}.mfp-s-ready .mfp-preloader{display:none}.mfp-s-error .mfp-content{display:none}button.mfp-close,button.mfp-arrow{overflow:visible;cursor:pointer;background:transparent;border:0;-webkit-appearance:none;display:block;outline:0;padding:0;z-index:1046;box-shadow:none;touch-action:manipulation}button::-moz-focus-inner{padding:0;border:0}.mfp-close{width:44px;height:44px;line-height:44px;position:absolute;right:0;top:0;text-decoration:none;text-align:center;opacity:.65;padding:0 0 18px 10px;color:#FFF;font-style:normal;font-size:28px;font-family:Arial,Baskerville,monospace}.mfp-close:hover,.mfp-close:focus{opacity:1}.mfp-close:active{top:1px}.mfp-close-btn-in .mfp-close{color:#333}.mfp-image-holder .mfp-close,.mfp-iframe-holder .mfp-close{color:#FFF;right:-6px;text-align:right;padding-right:6px;width:100%}.mfp-counter{position:absolute;top:0;right:0;color:#CCC;font-size:12px;line-height:18px;white-space:nowrap}.mfp-arrow{position:absolute;opacity:.65;margin:0;top:50%;margin-top:-55px;padding:0;width:90px;height:110px;-webkit-tap-highlight-color:transparent}.mfp-arrow:active{margin-top:-54px}.mfp-arrow:hover,.mfp-arrow:focus{opacity:1}.mfp-arrow:before,.mfp-arrow:after{content:'';display:block;width:0;height:0;position:absolute;left:0;top:0;margin-top:35px;margin-left:35px;border:medium inset transparent}.mfp-arrow:after{border-top-width:13px;border-bottom-width:13px;top:8px}.mfp-arrow:before{border-top-width:21px;border-bottom-width:21px;opacity:.7}.mfp-arrow-left{left:0}.mfp-arrow-left:after{border-right:17px solid #FFF;margin-left:31px}.mfp-arrow-left:before{margin-left:25px;border-right:27px solid #3f3f3f}.mfp-arrow-right{right:0}.mfp-arrow-right:after{border-left:17px solid #FFF;margin-left:39px}.mfp-arrow-right:before{border-left:27px solid #3f3f3f}.mfp-iframe-holder{padding-top:40px;padding-bottom:40px}.mfp-iframe-holder .mfp-content{line-height:0;width:100%;max-width:900px}.mfp-iframe-holder .mfp-close{top:-40px}.mfp-iframe-scaler{width:100%;height:0;overflow:hidden;padding-top:56.25%}.mfp-iframe-scaler iframe{position:absolute;display:block;top:0;left:0;width:100%;height:100%;box-shadow:0 0 8px rgba(0,0,0,0.6);background:#000}img.mfp-img{width:auto;max-width:100%;height:auto;display:block;line-height:0;box-sizing:border-box;padding:40px 0 40px;margin:0 auto}.mfp-figure{line-height:0}.mfp-figure:after{content:'';position:absolute;left:0;top:40px;bottom:40px;display:block;right:0;width:auto;height:auto;z-index:-1;box-shadow:0 0 8px rgba(0,0,0,0.6);background:#444}.mfp-figure small{color:#bdbdbd;display:block;font-size:12px;line-height:14px}.mfp-figure figure{margin:0}.mfp-bottom-bar{margin-top:-36px;position:absolute;top:100%;left:0;width:100%;cursor:auto}.mfp-title{text-align:left;line-height:18px;color:#f3f3f3;word-wrap:break-word;padding-right:36px}.mfp-image-holder .mfp-content{max-width:100%}.mfp-gallery .mfp-image-holder .mfp-figure{cursor:pointer}@media screen and (max-width:800px) and (orientation:landscape),screen and (max-height:300px){.mfp-img-mobile .mfp-image-holder{padding-left:0;padding-right:0}.mfp-img-mobile img.mfp-img{padding:0}.mfp-img-mobile .mfp-figure:after{top:0;bottom:0}.mfp-img-mobile .mfp-figure small{display:inline;margin-left:5px}.mfp-img-mobile .mfp-bottom-bar{background:rgba(0,0,0,0.6);bottom:0;margin:0;top:auto;padding:3px 5px;position:fixed;box-sizing:border-box}.mfp-img-mobile .mfp-bottom-bar:empty{padding:0}.mfp-img-mobile .mfp-counter{right:5px;top:3px}.mfp-img-mobile .mfp-close{top:0;right:0;width:35px;height:35px;line-height:35px;background:rgba(0,0,0,0.6);position:fixed;text-align:center;padding:0}}@media all and (max-width:900px){.mfp-arrow{-webkit-transform:scale(0.75);transform:scale(0.75)}.mfp-arrow-left{-webkit-transform-origin:0 0;transform-origin:0 0}.mfp-arrow-right{-webkit-transform-origin:100%;transform-origin:100%}.mfp-container{padding-left:6px;padding-right:6px}}
`;
const otherStyles = `
.r34-app-gallery-loader-info {
position: absolute;
z-index: 5000;
bottom: 10px;
right: 10px;
text-size: 8px;
color: white;
}
.r34-app-gallery-loader {
position: absolute;
z-index: 5000;
bottom: 45px;
right: 10px;
width: 40px;
height: 40px;
display: none;
}
.r34-app-gallery-loader::after {
content: " ";
display: block;
width: 36px;
height: 36px;
margin: 8px;
border-radius: 50%;
border: 6px solid #fff;
border-color: #fff transparent #fff transparent;
animation: lds-dual-ring 1.2s linear infinite;
}
.r34-app-gallery-loader.loading {
display: block;
}
@keyframes lds-dual-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
`;
var styleSheet = document.createElement("style");
styleSheet.innerText = styles;
document.head.appendChild(styleSheet);
var styleSheet2 = document.createElement("style");
styleSheet2.innerText = otherStyles;
document.head.appendChild(styleSheet2);
var open = false;
var initPlaySettingKey = "initPlay";
var playSpeedKey = "initPlaySpeed";
var isPlaying = getSetting(initPlaySettingKey);
var playSpeed = Number(getSetting(playSpeedKey) || 5000);
var playTimer = null;
var loading = document.createElement("div");
loading.classList.add("r34-app-gallery-loader");
document.body.appendChild(loading);
var info = document.createElement("div");
info.classList.add("r34-app-gallery-loader-info");
document.body.appendChild(info);
function startLoading() {
loading.classList.add("loading");
}
function stopLoading() {
loading.classList.remove("loading");
}
function updateInfo() {
info.innerHTML = "Gallery " + (isPlaying === "true" ? "Playing" : "Pause") + " / Speed: " + playSpeed / 1000 + "s";
}
function setPlaySpeed(speed) {
stop();
var speedToSet = speed;
if (speed < 1000) speedToSet = 1000;
if (speed > 15000) speedToSet = 15000;
setSetting(playSpeedKey, speedToSet.toString());
playSpeed = speedToSet;
play();
}
function playNext() {
if ($.magnificPopup.instance.items.length - 1 === $.magnificPopup.instance.index) {
movePage(1);
} else {
$.magnificPopup.instance.next();
}
}
function play() {
stop();
isPlaying = "true";
setSetting(initPlaySettingKey, "true");
if (!open) {
toggle();
}
playTimer = setInterval(function () {
playNext();
}, playSpeed);
}
function stop() {
if (isPlaying === "false") return;
isPlaying = "false";
clearTimeout(playTimer);
setSetting(initPlaySettingKey, "false");
}
function getImages() {
return $("main li .material-container img.w-full, main li .material-container video");
}
function toggle() {
if (open) {
$.magnificPopup.close();
open = false;
return;
}
var images = getImages();
var items = [];
images.each(function () {
var image = $(this);
if (image.is("img")) {
if (image.attr("alt") !== "Advertisement") {
const src = image.data("src");
items.push({
src: src,
type: "image",
});
}
} else {
items.push({
src: image.data("src"),
type: "iframe",
});
}
});
$.magnificPopup.open(
{
items: items,
gallery: {
enabled: true,
},
},
0
);
open = true;
}
var downloading = false;
function download(url, filename) {
if (downloading) return;
downloading = true;
startLoading();
fetch(url)
.then((response) => response.blob())
.then((blob) => {
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = filename;
link.click();
})
.catch(console.error)
.finally(() => {
downloading = false;
stopLoading();
});
}
function getImgUrl() {
return $.magnificPopup.instance.currItem.src;
}
function getPage() {
var searchParams = new URLSearchParams(window.location.search);
const pageParam = searchParams.has("page") ? searchParams.get("page") : 0;
return !Number.isNaN(Number(pageParam)) ? Number(pageParam) : 0;
}
function addParam(currentUrl, key, val) {
var url = new URL(currentUrl);
url.searchParams.set(key, val);
return url.href;
}
function movePage(offset) {
let page = getPage() + offset;
if (page < 0) page = 0;
window.location.href = addParam(window.location.href, "page", page);
}
function setSetting(setting, value) {
localStorage.setItem(setting, value);
}
function getSetting(setting) {
return localStorage.getItem(setting);
}
function init() {
if (isPlaying === "true") {
play();
}
updateInfo();
$(document).keypress(function (e) {
if (e.which == 53) {
stop();
// numeric 5
toggle();
} else if (e.which == 49) {
// numeric 1
movePage(-1);
} else if (e.which == 51) {
// numeric 2
movePage(1);
} else if (e.which == 56) {
// numeric 8
if (isPlaying === "true") {
stop();
} else {
play();
}
} else if (e.which == 55) {
// numeric 7
setPlaySpeed(playSpeed + 1000);
} else if (e.which == 57) {
// numeric 9
setPlaySpeed(playSpeed - 1000);
}
updateInfo();
if (!open) return;
if (e.which == 52) {
// numeric 4
$.magnificPopup.instance.prev();
} else if (e.which == 54) {
// numeric 6
$.magnificPopup.instance.next();
} else if (e.which == 50) {
// numeric 2
const url = getImgUrl();
download(url, url.substring(url.lastIndexOf("/") + 1));
}
});
}
function checkIfImageExists() {
var images = getImages();
if (images.length === 0) {
setTimeout(checkIfImageExists, 3000);
} else {
init();
}
}
setTimeout(checkIfImageExists, 3000);