fix(messenger): исправление прыжков при загрузке и дублирования скриптов

ПРОБЛЕМЫ:
1. Видимые прыжки прокрутки при загрузке чата
2. Принудительный скролл при получении чужих сообщений
3. Дублирование загрузки chat-detail-enhanced.js

РЕШЕНИЯ:
1. Используем requestAnimationFrame для гарантии обновления DOM перед прокруткой
   - Скрываем контейнер → рендерим → ждем RAF → скроллим → показываем
   - Прокрутка происходит ДО показа контейнера = нет видимых прыжков

2. Убираем агрессивный автоскролл в handleNewMessage:
   - Скроллим только если это наше сообщение ИЛИ мы уже внизу
   - Предотвращаем прерывание чтения старых сообщений

3. Убираем дублирование chat-detail-enhanced.js в шаблоне:
   - Было: загружается ДО chatDetail.js
   - Стало: загружается ПОСЛЕ для правильного порядка инициализации

4. Улучшен порядок загрузки скриптов в chat_detail.html:
   - emoji-picker (третья сторона)
   - chatDetail.js (core инициализация)
   - chat-detail-enhanced.js (UI расширения)

РЕЗУЛЬТАТЫ:
✅ Нет видимых прыжков - чат открывается сразу в конце
✅ Не прерывается чтение старых сообщений при приходе новых
✅ Правильный порядок инициализации компонентов
✅ Убрано дублирование загрузки скриптов
This commit is contained in:
Игорь Надеин 2026-01-12 11:03:41 +03:00
parent 86174fca6f
commit 07cd6acaff
2 changed files with 23 additions and 12 deletions

View File

@ -281,11 +281,14 @@ export function initUserWebSocket(options = {}) {
// Используем батчевый renderMessages вместо forEach для лучшей производительности
options.messageRenderer.renderMessages(messages);
// Устанавливаем scroll в конец ДО показа контейнера
state.scrollEl.scrollTop = state.scrollEl.scrollHeight;
// Показываем контейнер - пользователь сразу видит конец диалога
state.scrollEl.style.visibility = wasVisible || '';
// Используем requestAnimationFrame для гарантии что DOM обновлен перед прокруткой
requestAnimationFrame(() => {
// Устанавливаем scroll в конец ДО показа контейнера
state.scrollEl.scrollTop = state.scrollEl.scrollHeight;
// Показываем контейнер - пользователь сразу видит конец диалога
state.scrollEl.style.visibility = wasVisible || '';
});
// Инициализируем голосования после загрузки сообщений
if (window.chatPoll) {
@ -308,10 +311,16 @@ export function initUserWebSocket(options = {}) {
options.messageRenderer.renderMessage(message);
// Автоскролл если внизу
const isAtBottom = markReadApi?.atBottom?.() ?? true;
if (isAtBottom || message.author_id === userId) {
scrollToBottom();
// Автоскролл ТОЛЬКО если это наше сообщение ИЛИ мы уже внизу
// Предотвращаем принудительный скролл при получении чужих сообщений
const isAtBottom = markReadApi?.atBottom?.() ?? false;
const isOwnMessage = message.author_id === userId;
if (isOwnMessage || isAtBottom) {
// Используем requestAnimationFrame для плавности
requestAnimationFrame(() => {
scrollToBottom();
});
}
// Отмечаем как прочитанное

View File

@ -303,12 +303,14 @@
{# ========== THIRD-PARTY ========== #}
<script type="module" src="{% static 'vendor/emoji-picker/index.js' %}"></script>
{# ========== CHAT DETAIL - NEW ENHANCED VERSION ========== #}
<script type="module" src="{% static 'js/chat-detail-enhanced.js' %}"></script>
{# ========== CHAT DETAIL PAGE - CORE FUNCTIONALITY ========== #}
{# chatDetail.js инициализирует все компоненты в правильном порядке #}
<script type="module" src="{% static 'js/pages/chatDetail.js' %}"></script>
{# ========== CHAT DETAIL - UI ENHANCEMENTS ========== #}
{# Реакции, контекстное меню, выделение, голосования #}
<script type="module" src="{% static 'js/chat-detail-enhanced.js' %}"></script>
<script>
// Блокировка объявления
async function blockAnnouncement(chatId) {