SHA256
WIP: новая схема сообщений и push (не проверено)
This commit is contained in:
@@ -1,20 +1,59 @@
|
||||
import { renderHeader } from '../components/header.js';
|
||||
import { directMessages } from '../mock-data.js';
|
||||
import { addAppLogEntry, addChatMessage, getChatMessages, authService, state } from '../state.js';
|
||||
import {
|
||||
addAppLogEntry,
|
||||
addChatMessage,
|
||||
addOutgoingPendingMessage,
|
||||
getChatMessages,
|
||||
markChatRead,
|
||||
markOutgoingSent,
|
||||
authService,
|
||||
state,
|
||||
} from '../state.js';
|
||||
import { startOutgoingCall, hangupActiveCall } from '../services/call-service.js';
|
||||
|
||||
export const pageMeta = { id: 'chat-view', title: 'Чат' };
|
||||
|
||||
function parseBaseKey(baseKey) {
|
||||
const raw = String(baseKey || '').trim();
|
||||
const parts = raw.split('|');
|
||||
if (parts.length < 4) return null;
|
||||
const fromLogin = parts[0] || '';
|
||||
const toLogin = parts[1] || '';
|
||||
const timeMs = Number(parts[2] || 0);
|
||||
const nonce = Number(parts[3] || 0);
|
||||
if (!fromLogin || !toLogin || !Number.isFinite(timeMs) || !Number.isFinite(nonce)) return null;
|
||||
return { fromLogin, toLogin, timeMs, nonce };
|
||||
}
|
||||
|
||||
function renderLog(list, chatId) {
|
||||
list.innerHTML = '';
|
||||
const messages = getChatMessages(chatId);
|
||||
let unreadSeparatorInserted = false;
|
||||
messages.forEach((msg) => {
|
||||
if (!unreadSeparatorInserted && msg?.from === 'in' && msg?.unread) {
|
||||
const sep = document.createElement('div');
|
||||
sep.className = 'meta-muted';
|
||||
sep.style.textAlign = 'center';
|
||||
sep.style.margin = '8px 0';
|
||||
sep.textContent = 'Новые сообщения';
|
||||
list.append(sep);
|
||||
unreadSeparatorInserted = true;
|
||||
}
|
||||
|
||||
const bubble = document.createElement('div');
|
||||
bubble.className = `bubble ${msg.from}`;
|
||||
bubble.textContent = msg.text;
|
||||
let text = msg.text || '';
|
||||
if (msg.from === 'out') {
|
||||
if (msg.secondTick) text += ' ✓✓';
|
||||
else if (msg.firstTick) text += ' ✓';
|
||||
else text += ' …';
|
||||
}
|
||||
bubble.textContent = text;
|
||||
list.append(bubble);
|
||||
});
|
||||
list.scrollTop = list.scrollHeight;
|
||||
markChatRead(chatId);
|
||||
}
|
||||
|
||||
export function render({ navigate, route }) {
|
||||
@@ -27,6 +66,7 @@ export function render({ navigate, route }) {
|
||||
|
||||
const screen = document.createElement('section');
|
||||
screen.className = 'stack';
|
||||
const isKnownContact = (state.contacts || []).some((x) => String(x || '').toLowerCase() === String(chatId || '').toLowerCase());
|
||||
|
||||
screen.append(
|
||||
renderHeader({
|
||||
@@ -60,6 +100,37 @@ export function render({ navigate, route }) {
|
||||
})
|
||||
);
|
||||
|
||||
if (!isKnownContact) {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'card';
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'secondary-btn';
|
||||
btn.type = 'button';
|
||||
btn.textContent = 'Добавить в контакты';
|
||||
btn.addEventListener('click', async () => {
|
||||
try {
|
||||
await authService.addCloseFriend(chatId);
|
||||
state.contacts = [...new Set([...(state.contacts || []), chatId])];
|
||||
addAppLogEntry({
|
||||
level: 'info',
|
||||
source: 'contacts',
|
||||
message: `Пользователь ${chatId} добавлен в контакты`,
|
||||
});
|
||||
btn.disabled = true;
|
||||
btn.textContent = 'Добавлено';
|
||||
} catch (e) {
|
||||
addAppLogEntry({
|
||||
level: 'warn',
|
||||
source: 'contacts',
|
||||
message: 'Не удалось добавить пользователя в контакты',
|
||||
details: { login: chatId, error: e?.message || 'unknown' },
|
||||
});
|
||||
}
|
||||
});
|
||||
card.append(btn);
|
||||
screen.append(card);
|
||||
}
|
||||
|
||||
const wrap = document.createElement('div');
|
||||
wrap.className = 'chat-wrap';
|
||||
|
||||
@@ -79,7 +150,7 @@ export function render({ navigate, route }) {
|
||||
const text = input.value.trim();
|
||||
if (!text) return;
|
||||
|
||||
addChatMessage(chatId, text);
|
||||
const tempId = addOutgoingPendingMessage(chatId, text);
|
||||
input.value = '';
|
||||
renderLog(log, chatId);
|
||||
|
||||
@@ -90,16 +161,20 @@ export function render({ navigate, route }) {
|
||||
text,
|
||||
storagePwd: state.session.storagePwdInMemory,
|
||||
});
|
||||
markOutgoingSent(tempId, {
|
||||
messageKey: result?.outgoingKey || '',
|
||||
baseKey: result?.baseKey || result?.localBaseKey || '',
|
||||
});
|
||||
renderLog(log, chatId);
|
||||
addAppLogEntry({
|
||||
level: 'info',
|
||||
source: 'outgoing-dm',
|
||||
message: `Сообщение отправлено для ${chatId}`,
|
||||
details: {
|
||||
toLogin: chatId,
|
||||
messageId: result?.messageId || '',
|
||||
messageId: result?.outgoingKey || '',
|
||||
deliveredWsSessions: Number(result?.deliveredWsSessions || 0),
|
||||
deliveredWebPushSessions: Number(result?.deliveredWebPushSessions || 0),
|
||||
sessionNotFound: Boolean(result?.sessionNotFound),
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
@@ -118,7 +193,37 @@ export function render({ navigate, route }) {
|
||||
});
|
||||
|
||||
renderLog(log, chatId);
|
||||
void sendReadReceiptsForVisible();
|
||||
wrap.append(log, form);
|
||||
screen.append(wrap);
|
||||
return screen;
|
||||
}
|
||||
async function sendReadReceiptsForVisible() {
|
||||
const pending = getChatMessages(chatId)
|
||||
.filter((row) => row?.from === 'in' && Number(row?.messageType) === 1 && !row?.readReceiptSent)
|
||||
.slice(0, 50);
|
||||
for (const row of pending) {
|
||||
const ref = parseBaseKey(row.baseKey);
|
||||
if (!ref) continue;
|
||||
try {
|
||||
await authService.sendReadReceipt({
|
||||
login: state.session.login,
|
||||
toLogin: ref.fromLogin,
|
||||
storagePwd: state.session.storagePwdInMemory,
|
||||
refToLogin: ref.toLogin,
|
||||
refFromLogin: ref.fromLogin,
|
||||
refTimeMs: ref.timeMs,
|
||||
refNonce: ref.nonce,
|
||||
refType: 1,
|
||||
});
|
||||
row.readReceiptSent = true;
|
||||
} catch (e) {
|
||||
addAppLogEntry({
|
||||
level: 'warn',
|
||||
source: 'read-receipt',
|
||||
message: 'Не удалось отправить подтверждение прочтения',
|
||||
details: { chatId, messageKey: row.messageKey || '', error: e?.message || 'unknown' },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user