Corp/backend/static/js/pages/chatDetail.js

275 lines
9.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Chat Detail Page
* Инициализация страницы детального просмотра чата
*/
let initChatMarkRead, initChatComposer, initChatHistoryLoader, initChatFormManager, MessageRenderer, InitialMessagesLoader;
try {
const modules = await Promise.all([
import('../components/chatMarkRead.js'),
import('../components/chatComposer.js'),
import('../components/chatHistoryLoader.js'),
import('../components/chatFormManager.js'),
import('../components/messageRenderer.js'),
import('../components/initialMessagesLoader.js')
]);
initChatMarkRead = modules[0].initChatMarkRead;
initChatComposer = modules[1].initChatComposer;
initChatHistoryLoader = modules[2].initChatHistoryLoader;
initChatFormManager = modules[3].initChatFormManager;
MessageRenderer = modules[4].MessageRenderer;
InitialMessagesLoader = modules[5].InitialMessagesLoader;
} catch (error) {
console.error('[ChatDetail] Failed to load modules:', error);
alert('Ошибка загрузки модулей чата: ' + error.message);
throw error;
}
// Ждём DOM
function initWhenReady() {
// Получаем данные из data-атрибутов
const appContainer = document.getElementById('chatDetailApp');
if (!appContainer) {
console.warn('[ChatDetail] App container not found');
return;
}
// Читаем конфигурацию из data-атрибутов
const config = {
chatId: Number(appContainer.dataset.chatId),
userId: Number(appContainer.dataset.userId),
userName: appContainer.dataset.userName || 'Вы',
userAvatar: appContainer.dataset.userAvatar || '',
uploadUrl: appContainer.dataset.uploadUrl,
messagesUrl: appContainer.dataset.messagesUrl,
markReadUrl: appContainer.dataset.markReadUrl,
editUrlTemplate: appContainer.dataset.editUrlTemplate,
lastReadTimestamp: Number(appContainer.dataset.lastReadTimestamp) || null
};
// Читаем дополнительные URL из chatScroll (для рендеринга сообщений)
const chatScroll = document.getElementById('chatScroll');
if (chatScroll) {
config.profileUrl = chatScroll.dataset.profileUrl;
config.detailUrlTemplate = chatScroll.dataset.detailUrlTemplate;
}
console.log('[ChatDetail] Config:', config);
if (!config.chatId) {
console.error('[ChatDetail] chatId is required');
return;
}
// Ждём инициализации WebSocket
waitForWebSocket().then((userWs) => {
console.log('[ChatDetail] WebSocket ready, initializing components');
initializeComponents(config, userWs);
}).catch((error) => {
console.error('[ChatDetail] WebSocket initialization failed:', error);
});
}
// Запускаем инициализацию
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initWhenReady);
} else {
// DOM уже готов
initWhenReady();
}
/**
* Ожидание готовности WebSocket
*/
function waitForWebSocket() {
return new Promise((resolve, reject) => {
// Если уже готов - используем сразу
if (window.userWebSocket && window.userWebSocket.ws) {
console.log('[ChatDetail] WebSocket already available');
resolve(window.userWebSocket);
return;
}
// Ждём события с таймаутом
console.log('[ChatDetail] Waiting for user:ws-ready event...');
let timeoutId;
const handler = (e) => {
console.log('[ChatDetail] user:ws-ready event received');
clearTimeout(timeoutId);
resolve(e.detail.api);
};
window.addEventListener('user:ws-ready', handler, { once: true });
timeoutId = setTimeout(() => {
window.removeEventListener('user:ws-ready', handler);
reject(new Error('WebSocket initialization timeout'));
}, 10000); // 10 секунд
});
}
/**
* Инициализация всех компонентов страницы
*/
function initializeComponents(config, userWs) {
// ========== FORM MANAGER ==========
console.log('[ChatDetail] Initializing FormManager...');
const formManager = initChatFormManager({
formId: 'chatForm',
textareaId: 'id_content',
chatId: config.chatId,
uploadUrl: config.uploadUrl,
editUrlTemplate: config.editUrlTemplate
});
if (!formManager) {
console.error('[ChatDetail] FormManager initialization failed');
return;
}
console.log('[ChatDetail] FormManager initialized');
// ========== MARK READ ==========
console.log('[ChatDetail] Initializing MarkRead...');
const markReadApi = initChatMarkRead({
chatId: config.chatId,
meId: config.userId,
scrollContainerId: 'chatScroll',
textareaId: 'id_content',
formId: 'chatForm',
scrollBtnId: 'scrollBtn',
markReadUrl: config.markReadUrl,
initialLastReadTs: config.lastReadTimestamp
});
console.log('[ChatDetail] MarkRead initialized');
// ========== COMPOSER ==========
console.log('[ChatDetail] Initializing Composer...');
const composer = initChatComposer({
chatId: config.chatId,
formId: 'chatForm',
textareaId: 'id_content',
uploadUrl: config.uploadUrl,
meId: config.userId,
meName: config.userName,
meAvatar: config.userAvatar
});
if (!composer) {
console.error('[ChatDetail] Composer initialization failed');
return;
}
console.log('[ChatDetail] Composer initialized:', composer);
// ========== HISTORY LOADER ==========
console.log('[ChatDetail] Initializing HistoryLoader...');
// Получаем avatarMap если доступен
const avatarMap = window.chatAvatarMap?.getAll() || {};
const historyLoader = initChatHistoryLoader({
chatId: config.chatId,
scrollContainerId: 'chatScroll',
fetchUrl: config.messagesUrl,
avatarMap: avatarMap,
meId: config.userId
});
console.log('[ChatDetail] HistoryLoader initialized');
// ========== MESSAGE RENDERER ==========
console.log('[ChatDetail] Initializing MessageRenderer...');
const messageRenderer = new MessageRenderer({
containerId: 'chatScroll',
currentUserId: config.userId,
currentUserAvatar: config.userAvatar || '',
profileUrl: config.profileUrl || '/employees/profile/',
detailUrlTemplate: config.detailUrlTemplate || '/employees/detail/0/'
});
console.log('[ChatDetail] MessageRenderer initialized');
// ========== CONTEXT MENU ==========
// Инициализация контекстного меню перенесена в chat-detail-enhanced.js
// для избежания конфликтов и дублирования
// ========== INITIAL MESSAGES LOADER ==========
// ОТКЛЮЧЕНО: Используем WebSocket для загрузки initial_messages
// InitialMessagesLoader больше не нужен, так как WebSocket справляется с этой задачей
/*
console.log('[ChatDetail] Loading initial messages...');
const initialLoader = new InitialMessagesLoader({
chatId: config.chatId,
fetchUrl: config.messagesUrl,
limit: 30,
messageRenderer: messageRenderer,
onLoaded: (data) => {
console.log('[ChatDetail] Initial messages loaded:', data.messages.length);
// Скроллим вниз к последнему сообщению
const container = document.getElementById('chatScroll');
if (container) {
container.scrollTop = container.scrollHeight;
}
},
onError: (error) => {
console.error('[ChatDetail] Failed to load initial messages:', error);
alert('Ошибка загрузки сообщений: ' + error.message);
}
});
// Загружаем сообщения
initialLoader.load().catch(err => {
console.error('[ChatDetail] Initial load error:', err);
});
*/
console.log('[ChatDetail] Initial messages will be loaded via WebSocket');
// Убираем индикатор загрузки после подключения WebSocket
const loader = document.getElementById('initialLoader');
if (loader) {
// Скроем индикатор через WebSocket событие initial_messages
window.addEventListener('chat:initial-messages-loaded', () => {
loader.remove();
}, { once: true });
}
// ========== CONFIGURE WEBSOCKET ==========
console.log('[ChatDetail] Configuring WebSocket...');
if (userWs && userWs.configure) {
userWs.configure({
scrollContainerId: 'chatScroll',
formId: 'chatForm',
textareaId: 'id_content',
typingIndicatorId: 'typing',
avatarMap: avatarMap,
markReadApi: markReadApi,
messageRenderer: messageRenderer // Добавляем MessageRenderer
});
}
// Открываем чат в WebSocket с загрузкой истории
if (userWs && userWs.openChat) {
console.log('[ChatDetail] Opening chat in WebSocket with history:', config.chatId);
userWs.openChat(config.chatId, true); // true = загружаем initial_messages
}
// ========== EXPORT APIS ==========
window.chatComposer = composer;
window.chatHistoryLoader = historyLoader;
window.markReadApi = markReadApi;
window.chatFormManager = formManager;
// Контекстное меню и выделение сообщений инициализируются в chat-detail-enhanced.js
console.log('[ChatDetail] All components initialized successfully ✓');
}