🏠 返回首頁 

Greasy Fork is available in English.

✨ Simple Pull to Refresh

🌟 Minimal Premium: Простое и стабильное обновление страницы потягиванием для браузера Via

// ==UserScript==
// @name         ✨ Simple Pull to Refresh
// @namespace    r1kov
// @version      0.3-fix
// @description  🌟 Minimal Premium: Простое и стабильное обновление страницы потягиванием для браузера Via
// @match        *://*/*
// @grant        none
// @license      MIT
// ==/UserScript==
(function() {
'use strict';
const config = {
threshold: 100, // Минимальное расстояние для срабатывания обновления
elementId: 'simple-refresh',
overlayId: 'simple-overlay',
colors: {
pull: '#333',
release: '#ffcc00',
loading: '#007aff'
},
messages: {
pull: 'потяните вниз',
release: 'отпустите',
loading: 'обновление'
}
};
let state = {
startY: 0,
currentY: 0,
isActive: false
};
function injectStyles() {
const style = document.createElement('style');
style.textContent = `
#${config.elementId} {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 64px;
display: flex;
align-items: center;
justify-content: center;
z-index: 999999;
transform: translateY(-100%);
transition: transform 0.3s ease-out;
pointer-events: none;
font-family: -apple-system, system-ui, sans-serif;
}
#${config.elementId} .pill {
display: flex;
align-items: center;
gap: 8px;
padding: 12px 20px;
background: ${config.colors.pull};
color: white;
border-radius: 26px;
font-size: 14px;
font-weight: 500;
transition: background 0.3s ease-out;
}
#${config.elementId} .icon {
font-size: 18px;
}
#${config.overlayId} {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0);
backdrop-filter: blur(0px);
-webkit-backdrop-filter: blur(0px);
z-index: 999998;
pointer-events: none;
transition: all 0.3s ease-out;
}
@keyframes rotate {
to { transform: rotate(360deg); }
}
`;
document.head.appendChild(style);
}
function createElements() {
if (document.getElementById(config.elementId) || document.getElementById(config.overlayId)) {
return {
overlay: document.getElementById(config.overlayId),
refreshEl: document.getElementById(config.elementId)
};
}
const overlay = document.createElement('div');
overlay.id = config.overlayId;
document.body.appendChild(overlay);
const refreshEl = document.createElement('div');
refreshEl.id = config.elementId;
refreshEl.innerHTML = `
<div class="pill">
<span class="icon">↓</span>
<span class="text">${config.messages.pull}</span>
</div>
`;
document.body.appendChild(refreshEl);
return { overlay, refreshEl };
}
function updateUI(distance) {
const { overlay, refreshEl } = createElements();
const translateY = Math.min(distance * 0.5, 64);
refreshEl.style.transform = `translateY(${translateY - 64}px)`;
overlay.style.background = `rgba(255, 255, 255, ${distance / config.threshold * 0.1})`;
overlay.style.backdropFilter = `blur(${distance / config.threshold * 8}px)`;
overlay.style.webkitBackdropFilter = `blur(${distance / config.threshold * 8}px)`;
if (distance > config.threshold) {
refreshEl.querySelector('.pill').style.background = config.colors.release;
refreshEl.querySelector('.text').textContent = config.messages.release;
} else {
refreshEl.querySelector('.pill').style.background = config.colors.pull;
refreshEl.querySelector('.text').textContent = config.messages.pull;
}
}
function reset() {
const { overlay, refreshEl } = createElements();
refreshEl.style.transform = 'translateY(-100%)';
overlay.style.background = 'rgba(255, 255, 255, 0)';
overlay.style.backdropFilter = 'blur(0px)';
overlay.style.webkitBackdropFilter = 'blur(0px)';
setTimeout(() => {
if (refreshEl && refreshEl.parentNode) refreshEl.remove();
if (overlay && overlay.parentNode) overlay.remove();
}, 300);
}
function refresh() {
const { refreshEl } = createElements();
refreshEl.querySelector('.pill').style.background = config.colors.loading;
refreshEl.querySelector('.icon').textContent = '↻';
refreshEl.querySelector('.text').textContent = config.messages.loading;
setTimeout(() => {
window.location.reload();
}, 300);
}
function handleTouchStart(e) {
if (window.scrollY === 0 && !e.target.matches('input, textarea, select')) {
state.startY = e.touches[0].pageY;
state.currentY = state.startY;
state.isActive = true;
}
}
function handleTouchMove(e) {
if (!state.isActive) return;
state.currentY = e.touches[0].pageY;
const distance = state.currentY - state.startY;
if (distance > 0 && window.scrollY === 0) {
e.preventDefault();
requestAnimationFrame(() => updateUI(distance));
}
}
function handleTouchEnd() {
if (!state.isActive) return;
const distance = state.currentY - state.startY;
if (distance > config.threshold) {
refresh();
} else {
reset();
}
state.isActive = false;
}
injectStyles();
document.addEventListener('touchstart', handleTouchStart, { passive: true });
document.addEventListener('touchmove', handleTouchMove, { passive: false });
document.addEventListener('touchend', handleTouchEnd, { passive: true });
// Очистка элементов при переходе на другую страницу
window.addEventListener('beforeunload', () => {
const refreshEl = document.getElementById(config.elementId);
const overlay = document.getElementById(config.overlayId);
if (refreshEl && refreshEl.parentNode) refreshEl.remove();
if (overlay && overlay.parentNode) overlay.remove();
});
})();