Sleazy Fork is available in English.
Floating account, search, menu, like and favorite controls Works alongside https://greasyfork.org/en/scripts/592307-peach-video-adblock
La data de
// ==UserScript==
// @name Tiny Floating Controls
// @namespace local.floating-controls
// @version 1.1.0
// @description Floating account, search, menu, like and favorite controls Works alongside https://greasyfork.org/en/scripts/592307-peach-video-adblock
// @match https://www.pornhub.com/*
// @run-at document-start
// @grant none
// ==/UserScript==
(() => {
'use strict';
/* =========================================================
CONFIG
========================================================= */
const BUTTONS = {
account: {
id: 'tiny-floating-account-button',
text: '●',
label: 'Account',
right: 8,
bottom: 8,
size: 26,
fontSize: 14
},
search: {
id: 'tiny-floating-search-button',
text: '⌕',
label: 'Search',
right: 8,
bottom: 42,
size: 26,
fontSize: 17
},
menu: {
id: 'tiny-floating-left-menu-toggle',
text: '☰',
label: 'Toggle left menu',
right: 8,
bottom: 75,
size: 28,
fontSize: 14
},
like: {
id: 'tiny-floating-like-button',
text: '👍',
label: 'Like video',
right: 8,
bottom: 109,
size: 26,
fontSize: 15
},
favorite: {
id: 'tiny-floating-favorite-button',
text: '❤️',
label: 'Add video to favorite',
right: 8,
bottom: 142,
size: 26,
fontSize: 15
}
};
/* =========================================================
NATIVE ELEMENTS
========================================================= */
function getAccountMenu() {
return document.querySelector('#rightMenu');
}
function getSearch() {
return document.querySelector('#searchSection');
}
function getLeftMenu() {
return document.querySelector('#leftMenu');
}
function clickNativeButton(selector) {
const button = document.querySelector(selector);
if (!button) return;
button.click();
}
/* =========================================================
ACCOUNT
========================================================= */
function toggleAccount() {
const menu = getAccountMenu();
if (!menu) return;
menu.classList.toggle('active');
}
/* =========================================================
SEARCH
========================================================= */
function toggleSearch() {
const search = getSearch();
if (!search) return;
search.classList.toggle('active');
if (search.classList.contains('active')) {
const input = search.querySelector('#search_text');
if (input) {
setTimeout(() => {
input.focus();
}, 50);
}
}
}
/* =========================================================
LEFT MENU
========================================================= */
function openLeftMenu() {
const menu = getLeftMenu();
if (!menu) return;
menu.classList.add('active');
menu.removeAttribute('hidden');
menu.style.removeProperty('display');
menu.style.removeProperty('visibility');
menu.style.removeProperty('transform');
}
function closeLeftMenu() {
const menu = getLeftMenu();
if (!menu) return;
menu.classList.remove('active');
}
function toggleLeftMenu() {
const menu = getLeftMenu();
if (!menu) return;
if (menu.classList.contains('active')) {
closeLeftMenu();
} else {
openLeftMenu();
}
}
function likeVideo() {
clickNativeButton('#thumbs-up');
}
function favoriteVideo() {
clickNativeButton('#favoriteBtn');
}
/* =========================================================
SHARED DRAGGABLE BUTTON
========================================================= */
function makeDraggable(button, onTap) {
let dragging = false;
let moved = false;
let startX = 0;
let startY = 0;
let startLeft = 0;
let startTop = 0;
button.addEventListener('pointerdown', event => {
dragging = true;
moved = false;
startX = event.clientX;
startY = event.clientY;
const rect = button.getBoundingClientRect();
startLeft = rect.left;
startTop = rect.top;
try {
button.setPointerCapture(event.pointerId);
} catch (_) {}
});
button.addEventListener('pointermove', event => {
if (!dragging) return;
const dx = event.clientX - startX;
const dy = event.clientY - startY;
if (Math.abs(dx) > 4 || Math.abs(dy) > 4) {
moved = true;
}
button.style.left = `${startLeft + dx}px`;
button.style.top = `${startTop + dy}px`;
button.style.right = 'auto';
button.style.bottom = 'auto';
});
button.addEventListener('pointerup', event => {
dragging = false;
try {
button.releasePointerCapture(event.pointerId);
} catch (_) {}
});
button.addEventListener('pointercancel', () => {
dragging = false;
});
button.addEventListener('click', event => {
if (moved) {
moved = false;
return;
}
event.preventDefault();
event.stopPropagation();
onTap();
});
}
/* =========================================================
CREATE FLOATING BUTTON
========================================================= */
function createButton(config, onTap) {
if (
!document.body ||
document.getElementById(config.id)
) {
return;
}
const button = document.createElement('button');
button.id = config.id;
button.type = 'button';
button.textContent = config.text;
button.setAttribute(
'aria-label',
config.label
);
Object.assign(button.style, {
position: 'fixed',
right: `${config.right}px`,
bottom: `${config.bottom}px`,
width: `${config.size}px`,
height: `${config.size}px`,
padding: '0',
margin: '0',
border: '0',
borderRadius: '50%',
background: 'rgba(0,0,0,.65)',
color: '#fff',
fontSize: `${config.fontSize}px`,
lineHeight: `${config.size}px`,
textAlign: 'center',
zIndex: '2147483647',
opacity: '.55',
cursor: 'pointer',
userSelect: 'none',
WebkitUserSelect: 'none',
touchAction: 'none',
boxShadow: '0 1px 4px rgba(0,0,0,.4)'
});
document.body.appendChild(button);
makeDraggable(button, onTap);
}
function createFloatingControls() {
if (!document.body) return;
const actions = {
account: toggleAccount,
search: toggleSearch,
menu: toggleLeftMenu,
like: likeVideo,
favorite: favoriteVideo
};
for (const [name, config] of Object.entries(BUTTONS)) {
createButton(config, actions[name]);
}
}
function init() {
if (!document.body) {
requestAnimationFrame(init);
return;
}
createFloatingControls();
}
init();
})();