SHiNE-server/shine-UI/js/pages/messages/dm-lab-chat.js

71 lines
3.0 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.

// Demo-чат для оффлайн-флоу /messages-list/lab/chat/:id (только demo).
// Реальный chat-view.js НЕ трогаем (он завязан на бэкенд/WS); здесь — изолированная мок-страница.
// Состояние сообщений берём из dm-lab-store (localStorage). Без сети, без авторизации.
import { directMessages } from '../../mock-data.js';
import { getThread, appendOut, markRead } from './dm-lab-store.js';
// showAppChrome:false — у чата свой низ (поле ввода), нижнее меню прячем.
export const pageMeta = { id: 'dm-lab-chat', title: 'Чат (demo)', showAppChrome: false };
function findDialog(id) {
return (Array.isArray(directMessages) ? directMessages : []).find((m) => m.id === id) || null;
}
function bubble(m) {
const b = document.createElement('div');
b.className = `bubble ${m && m.from === 'out' ? 'out' : 'in'}`;
b.textContent = m ? m.text : '';
return b;
}
export function render({ navigate, route }) {
const chatId = String(route?.params?.chatId || '').trim();
const dialog = findDialog(chatId);
const name = (dialog && dialog.name) || chatId || 'Диалог';
// Открытие диалога сбрасывает у него непрочитанные (demo).
markRead(chatId);
const screen = document.createElement('section');
screen.className = 'dm-screen dm-chat-screen';
// Шапка чата: назад + имя собеседника + demo-метка.
const head = document.createElement('header');
head.className = 'dm-chat-head';
head.innerHTML = `
<button type="button" class="dm-chat-back" aria-label="Назад"></button>
<span class="dm-chat-peer">${name}</span>
<span class="dm-chat-demo-tag">demo</span>
`;
head.querySelector('.dm-chat-back').addEventListener('click', () => navigate('messages-list/lab'));
const log = document.createElement('div');
log.className = 'dm-messages-log';
getThread(chatId).forEach((m) => log.append(bubble(m)));
const inputRow = document.createElement('form');
inputRow.className = 'dm-chat-input';
inputRow.innerHTML = `
<textarea class="dm-input" rows="1" placeholder="Сообщение…" aria-label="Текст сообщения"></textarea>
<button type="submit" class="dm-send-btn dm-send-icon-btn" aria-label="Отправить">➤</button>
`;
const field = inputRow.querySelector('.dm-input');
const scrollToEnd = () => requestAnimationFrame(() => { log.scrollTop = log.scrollHeight; });
const submit = () => {
const msg = appendOut(chatId, field.value);
if (!msg) return;
field.value = '';
log.append(bubble(msg));
scrollToEnd();
};
inputRow.addEventListener('submit', (e) => { e.preventDefault(); submit(); });
field.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); submit(); }
});
screen.append(head, log, inputRow);
scrollToEnd();
return screen;
}