Додан фільтр на сторінці керування вісниками.
Виправлено помилки.
This commit is contained in:
@@ -19,6 +19,8 @@ class SwipeUpdater extends HTMLElement {
|
||||
|
||||
// 3. Внутрішній стан
|
||||
this._isReadyToReload = false; // Прапорець, що вказує на готовність до оновлення
|
||||
this._isStandalone = false; // Кеш для перевірки PWA режиму
|
||||
this._isTouching = false; // Чи тримає користувач палець на екрані
|
||||
|
||||
// 4. Створення елементів (Внутрішній HTML)
|
||||
shadow.innerHTML = `
|
||||
@@ -111,8 +113,10 @@ class SwipeUpdater extends HTMLElement {
|
||||
this._animID = shadow.getElementById('swipe_updater');
|
||||
this._animIconID = shadow.getElementById('swipe_icon');
|
||||
|
||||
// 6. Прив'язка контексту `this` для обробника подій (важливо для коректної роботи `this.handleScroll`)
|
||||
// 6. Прив'язка контексту `this` для обробників подій
|
||||
this.handleScroll = this.handleScroll.bind(this);
|
||||
this.handleTouchStart = this.handleTouchStart.bind(this);
|
||||
this.handleTouchEnd = this.handleTouchEnd.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,51 +132,81 @@ class SwipeUpdater extends HTMLElement {
|
||||
}
|
||||
}
|
||||
|
||||
// Фіксуємо, що користувач торкнувся екрана
|
||||
handleTouchStart() {
|
||||
this._isTouching = true;
|
||||
}
|
||||
|
||||
// Обробка події, коли користувач відпускає екран
|
||||
handleTouchEnd() {
|
||||
this._isTouching = false;
|
||||
const threshold = -165;
|
||||
|
||||
// Якщо палець відпустили, а ефект «гумового скролу» вже повернувся вище порогу
|
||||
// (тобто користувач передумав і потягнув назад вгору перед тим як відпустити)
|
||||
if (window.scrollY > threshold && this._isReadyToReload) {
|
||||
this._resetRefreshState();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Обробник події скролу (головна логіка Pull-to-Refresh).
|
||||
* Відстежує прокручування вище верхньої межі сторінки (`window.scrollY < 0`).
|
||||
*/
|
||||
handleScroll() {
|
||||
// Перевірка на режим Standalone (PWA) - функціональність актуальна переважно тут
|
||||
const isStandalone = window.matchMedia('(display-mode: standalone)').matches;
|
||||
if (!this._isStandalone) return;
|
||||
|
||||
if (isStandalone) {
|
||||
let scrollY = window.scrollY;
|
||||
|
||||
// 1. Анімація іконки під час прокручування за верхню межу (scrollY < 0)
|
||||
if (scrollY <= -10) {
|
||||
// Зміщення іконки разом із прокруткою
|
||||
this._animIconID.style.top = `${scrollY / 1.5}px`;
|
||||
this._animID.style.zIndex = '115'; // Піднімаємо z-index для видимості над контентом
|
||||
} else {
|
||||
this._animID.style.zIndex = '0'; // Повертаємо базовий z-index
|
||||
const scrollY = window.scrollY;
|
||||
const threshold = -165; // Поріг прокрутки (наприклад, -125px) для активації оновлення
|
||||
|
||||
// 1. Анімація іконки під час прокручування за верхню межу (scrollY < 0)
|
||||
if (scrollY <= -10) {
|
||||
// Зміщення іконки разом із прокруткою
|
||||
this._animIconID.style.top = `${scrollY / 1.5}px`;
|
||||
this._animID.style.zIndex = '115'; // Піднімаємо z-index для видимості над контентом
|
||||
} else {
|
||||
this._animIconID.style.top = '0px';
|
||||
this._animID.style.zIndex = '0'; // Повертаємо базовий z-index
|
||||
}
|
||||
|
||||
// 2. Логіка активації "готовий до оновлення"
|
||||
if (scrollY <= threshold) {
|
||||
if (!this._isReadyToReload) {
|
||||
this._isReadyToReload = true;
|
||||
// Поворот іконки на 180 градусів
|
||||
this._animIconID.style.transform = 'rotate(180deg)';
|
||||
this._animIconID.setAttribute('data-state', ''); // Деактивація стану "active"
|
||||
}
|
||||
|
||||
const threshold = -125; // Поріг прокрутки (наприклад, -125px) для активації оновлення
|
||||
|
||||
// 2. Логіка активації "готовий до оновлення"
|
||||
if (scrollY <= threshold) {
|
||||
if (!this._isReadyToReload) {
|
||||
this._isReadyToReload = true;
|
||||
// Поворот іконки на 180 градусів
|
||||
this._animIconID.style.transform = 'rotate(180deg)';
|
||||
this._animIconID.setAttribute('data-state', ''); // Деактивація стану "active"
|
||||
}
|
||||
}
|
||||
// 3. Логіка виклику оновлення та скидання стану
|
||||
// Якщо користувач відпускає свайп (scrollY повертається до >= 0) І був готовий до оновлення
|
||||
else if (scrollY >= 0) {
|
||||
if (this._isReadyToReload) {
|
||||
// Виклик користувацької функції (або стандартного window.location.reload())
|
||||
this._appReload();
|
||||
|
||||
// Скидання стану та анімації
|
||||
this._isReadyToReload = false;
|
||||
this._animIconID.style.transform = 'rotate(0deg)';
|
||||
this._animIconID.setAttribute('data-state', 'active');
|
||||
}
|
||||
}
|
||||
// Скасування жесту під час руху пальцем вгору (ще до відпускання)
|
||||
else if (scrollY > threshold && scrollY < 0 && this._isTouching) {
|
||||
if (this._isReadyToReload) {
|
||||
this._isReadyToReload = false;
|
||||
this._animIconID.style.transform = 'rotate(0deg)';
|
||||
this._animIconID.setAttribute('data-state', 'active');
|
||||
}
|
||||
}
|
||||
// 3. Логіка виклику оновлення, коли сторінка повернулась до нуля
|
||||
else if (scrollY >= 0) {
|
||||
if (this._isReadyToReload) {
|
||||
this._appReload();
|
||||
this._resetRefreshState();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Допоміжний метод для повного скидання графічного стану
|
||||
*/
|
||||
_resetRefreshState() {
|
||||
this._isReadyToReload = false;
|
||||
this._animIconID.style.transform = 'rotate(0deg)';
|
||||
this._animIconID.setAttribute('data-state', 'active');
|
||||
this._animIconID.style.top = '0px';
|
||||
this._animID.style.zIndex = '0';
|
||||
}
|
||||
|
||||
|
||||
@@ -181,8 +215,15 @@ class SwipeUpdater extends HTMLElement {
|
||||
* Додаємо обробник події прокручування.
|
||||
*/
|
||||
connectedCallback() {
|
||||
// Прослуховування глобальної події скролу
|
||||
window.addEventListener('scroll', this.handleScroll);
|
||||
// Перевіряємо PWA режим ОДИН раз при додаванні компонента на сторінку
|
||||
this._isStandalone = window.matchMedia('(display-mode: standalone)').matches;
|
||||
|
||||
if (this._isStandalone) {
|
||||
window.addEventListener('scroll', this.handleScroll);
|
||||
// passive: true покращує продуктивність скролу на мобільних пристроях
|
||||
window.addEventListener('touchstart', this.handleTouchStart, { passive: true });
|
||||
window.addEventListener('touchend', this.handleTouchEnd, { passive: true });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,12 +231,17 @@ class SwipeUpdater extends HTMLElement {
|
||||
* Видаляємо обробник події прокручування для запобігання витоку пам'яті.
|
||||
*/
|
||||
disconnectedCallback() {
|
||||
// Чистимо абсолютно всі додані слухачі
|
||||
window.removeEventListener('scroll', this.handleScroll);
|
||||
window.removeEventListener('touchstart', this.handleTouchStart);
|
||||
window.removeEventListener('touchend', this.handleTouchEnd);
|
||||
}
|
||||
}
|
||||
|
||||
// Реєстрація веб-компонента
|
||||
customElements.define('swipe-updater', SwipeUpdater);
|
||||
if (!customElements.get('swipe-updater')) {
|
||||
customElements.define('swipe-updater', SwipeUpdater);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user