From e7ab9893e4f59248277d72ef52d0f11bc4c4bad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=9D=D0=B0=D0=B4=D0=B5?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Tue, 13 Jan 2026 09:35:42 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D1=83=20isN?= =?UTF-8?q?earBottom=20=D0=B2=20IntersectionObserver=20=D1=87=D1=82=D0=BE?= =?UTF-8?q?=D0=B1=D1=8B=20=D0=B8=D0=B7=D0=B1=D0=B5=D0=B6=D0=B0=D1=82=D1=8C?= =?UTF-8?q?=20=D0=BB=D0=BE=D0=B6=D0=BD=D0=BE=D0=B3=D0=BE=20=D1=81=D1=80?= =?UTF-8?q?=D0=B0=D0=B1=D0=B0=D1=82=D1=8B=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - проблема: Observer срабатывал сразу после init когда scrollTop=0 - первое сообщение было видимо → автоматическая загрузка истории - решение: не загружаем историю если пользователь внизу (isNearBottom) - это предотвращает ложное срабатывание при инициализации --- backend/static/js/managers/scrollManagerV2.js | 63 +++++++++++++++++-- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/backend/static/js/managers/scrollManagerV2.js b/backend/static/js/managers/scrollManagerV2.js index 9279fbde..453e435a 100644 --- a/backend/static/js/managers/scrollManagerV2.js +++ b/backend/static/js/managers/scrollManagerV2.js @@ -95,14 +95,28 @@ export class ScrollManagerV2 { * @returns {Promise} */ async init() { + console.log('[ScrollManagerV2] 🔵 INIT STARTED'); + console.log('[ScrollManagerV2] Initial scroll state:', { + scrollTop: this.scrollEl.scrollTop, + scrollHeight: this.scrollEl.scrollHeight, + clientHeight: this.scrollEl.clientHeight, + isNearBottom: this.isNearBottom(), + messagesCount: this.scrollEl.querySelectorAll('.msg').length + }); + // Ждем стабилизации DOM await this._waitForLayout(); + console.log('[ScrollManagerV2] After layout wait:', { + scrollTop: this.scrollEl.scrollTop, + scrollHeight: this.scrollEl.scrollHeight + }); + this._setupIntersectionObserver(); this._setupScrollListener(); this._setupResizeListener(); - console.log('[ScrollManagerV2] Initialized'); + console.log('[ScrollManagerV2] 🟢 INIT COMPLETE'); } /** @@ -380,14 +394,23 @@ export class ScrollManagerV2 { * @private */ _setupIntersectionObserver() { + console.log('[ScrollManagerV2] 🔍 _setupIntersectionObserver called'); + // Находим первое сообщение const firstMessage = this.scrollEl.querySelector('.msg[data-message-id]'); if (!firstMessage) { - console.log('[ScrollManagerV2] No messages yet, observer not set'); + console.log('[ScrollManagerV2] ❌ No messages yet, observer not set'); return; } + console.log('[ScrollManagerV2] First message found:', { + messageId: firstMessage.dataset.messageId, + offsetTop: firstMessage.offsetTop, + scrollTop: this.scrollEl.scrollTop, + firstMessageVisible: firstMessage.getBoundingClientRect().top < this.scrollEl.clientHeight + }); + // Создаем observer this._historyObserver = new IntersectionObserver( (entries) => this._handleIntersection(entries), @@ -399,7 +422,7 @@ export class ScrollManagerV2 { ); this._historyObserver.observe(firstMessage); - console.log('[ScrollManagerV2] Observer attached to first message'); + console.log('[ScrollManagerV2] ✅ Observer attached to first message'); } /** @@ -433,13 +456,45 @@ export class ScrollManagerV2 { * @private */ _handleIntersection(entries) { + console.log('[ScrollManagerV2] 👁️ IntersectionObserver triggered:', { + entriesCount: entries.length, + scrollTop: this.scrollEl.scrollTop, + scrollHeight: this.scrollEl.scrollHeight, + isNearBottom: this.isNearBottom() + }); + entries.forEach(entry => { - if (entry.isIntersecting && !this._isLoadingHistory) { + console.log('[ScrollManagerV2] Entry:', { + target: entry.target.dataset?.messageId, + isIntersecting: entry.isIntersecting, + intersectionRatio: entry.intersectionRatio, + isLoadingHistory: this._isLoadingHistory, + isNearBottom: this.isNearBottom(), + willLoadHistory: entry.isIntersecting && !this._isLoadingHistory && !this.isNearBottom() + }); + + // ✅ ВАЖНО: НЕ загружаем историю если пользователь внизу! + // Это предотвращает ложное срабатывание при инициализации + if (entry.isIntersecting && !this._isLoadingHistory && !this.isNearBottom()) { + console.log('[ScrollManagerV2] 🚀 Triggering debounced history load...'); this._debouncedLoadHistory(); + } else if (entry.isIntersecting && this.isNearBottom()) { + console.log('[ScrollManagerV2] 🚫 User at bottom, skipping history load (false positive)'); + } else if (entry.isIntersecting && this._isLoadingHistory) { + console.log('[ScrollManagerV2] ⏸️ Already loading history, skipping'); } }); } + /** + * Триггер загрузки истории + * @private + */ + _triggerLoadHistory() { + console.log('[ScrollManagerV2] 🎬 _triggerLoadHistory called (from debounced)'); + this.loadMoreHistory(); + } + /** * Обработчик скролла * @private