ГЛУБОКИЙ АУДИТ выявил корневые причины прыжков:
НАЙДЕННЫЕ ПРОБЛЕМЫ:
1. chatMarkRead делал свою прокрутку ПОСЛЕ handleInitialMessages
- mark.scrollIntoView() или autoscroll() в requestAnimationFrame
- Конфликтовал с уже установленной прокруткой
2. Дублирование обработчика кнопки 'вниз':
- chatMarkRead.js: btn.addEventListener
- chat-detail-enhanced.js: scrollBtn.addEventListener
- Два обработчика на одну кнопку!
3. Излишняя сложность в scrollToBottom():
- Вызывал markReadApi.autoscroll() вместо прямой установки
- Дополнительный уровень косвенности = источник багов
ИСПРАВЛЕНИЯ:
1. chatMarkRead НЕ скроллит при инициализации:
- Divider создается, но не скроллится к нему
- Прокрутка управляется ТОЛЬКО из handleInitialMessages
- Единая точка ответственности
2. Убрано дублирование кнопки:
- Удален обработчик из chat-detail-enhanced.js
- Остался только в chatMarkRead.js
3. Упрощен scrollToBottom():
- Прямая установка scrollTop вместо вызова markReadApi
- Поддержка instant режима (без анимации)
- Предсказуемое поведение
4. Добавлены комментарии и документация:
- Пояснено почему НЕ скроллим в chatMarkRead
- Описано назначение каждой функции прокрутки
- Создан полный аудит в docs/completed/SCROLL_CONFLICTS_AUDIT.md
АРХИТЕКТУРА ПРОКРУТКИ:
✅ При загрузке: ТОЛЬКО handleInitialMessages
✅ Кнопка вниз: chatMarkRead.autoscroll()
✅ Новые сообщения: ТОЛЬКО если свое ИЛИ уже внизу
✅ Ввод текста: autoscroll() если внизу
РЕЗУЛЬТАТ:
✅ Нет прыжков - единая точка управления прокруткой
✅ Нет конфликтов - каждая функция делает одно
✅ Нет дублирования - один обработчик на событие
✅ Предсказуемость - прямые вызовы вместо косвенных
Файлы:
- userWebSocket.js: упрощен scrollToBottom
- chatMarkRead.js: убрана автопрокрутка при инициализации
- chat-detail-enhanced.js: убран дублирующий обработчик
- docs/completed/SCROLL_CONFLICTS_AUDIT.md: полный аудит
ПРОБЛЕМЫ:
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 расширения)
РЕЗУЛЬТАТЫ:
✅ Нет видимых прыжков - чат открывается сразу в конце
✅ Не прерывается чтение старых сообщений при приходе новых
✅ Правильный порядок инициализации компонентов
✅ Убрано дублирование загрузки скриптов
Проблема: При открытии чата сначала загружались сообщения,
затем происходила видимая прокрутка вниз - плохой UX
Решение:
1. Скрываем контейнер (visibility: hidden) перед рендерингом
2. Используем DocumentFragment в renderMessages для батчевой вставки
3. Устанавливаем scrollTop ДО показа контейнера
4. Показываем контейнер - пользователь сразу видит конец диалога
Преимущества:
- Нет видимой прокрутки - сразу показывается конец чата
- Меньше reflow (1 вместо N при forEach)
- Быстрее рендеринг больших чатов (все элементы вставляются за раз)
- Лучший UX - нет "прыжков" при загрузке
Изменения:
- userWebSocket.js: добавлено скрытие/показ контейнера, прямая установка scrollTop
- messageRenderer.js: renderMessages использует DocumentFragment вместо множественных insertAdjacentHTML
- Удалён chatWebSocket.js (дублировал userWebSocket.js)
- Удалён initialMessagesLoader.js (не используется, загрузка через WS)
- Очищены импорты и закомментированный код в chatDetail.js
- Добавлен план рефакторинга в docs/in-progress/
Загрузка initial messages теперь происходит только через:
- userWebSocket.handleInitialMessages() - начальные сообщения
- chatHistoryLoader - подгрузка истории при скролле