Fix DM name fallbacks and chat header

This commit is contained in:
AidarKC
2026-09-02 14:23:42 +04:00
parent 079be37fff
commit 53cd55a2a0
4 changed files with 85 additions and 41 deletions
+57 -40
View File
@@ -128,7 +128,7 @@ function createChatHeaderParts(login, navigate) {
loginEl.setAttribute('role', 'heading');
loginEl.setAttribute('aria-level', '1');
loginEl.setAttribute('aria-label', `Чат с ${cleanLogin}`);
loginEl.innerHTML = `<span class="chat-header-display-name">${cleanLogin}</span><span class="chat-header-user-login">${cleanLogin}</span>`;
loginEl.innerHTML = `<span class="chat-header-display-name">${cleanLogin}</span><span class="chat-header-user-login" hidden>${cleanLogin}</span>`;
void loadProfileSnapshot(cleanLogin)
.then((snapshot) => {
@@ -153,7 +153,10 @@ function createChatHeaderParts(login, navigate) {
const nameNode = loginEl.querySelector('.chat-header-display-name');
const loginNode = loginEl.querySelector('.chat-header-user-login');
if (nameNode) nameNode.textContent = display;
if (loginNode) loginNode.textContent = cleanLogin;
if (loginNode) {
loginNode.textContent = cleanLogin;
loginNode.hidden = display === cleanLogin;
}
}
})
.catch(() => {});
@@ -967,7 +970,6 @@ export function render({ navigate, route, chrome }) {
const screen = document.createElement('section');
screen.className = 'stack dm-screen dm-chat-screen';
const isTextToSpeechReady = isTextToSpeechConfigured(state.entrySettings);
const isKnownContact = (state.contacts || []).some((x) => String(x || '').toLowerCase() === String(chatId || '').toLowerCase());
const hasUnreadIncoming = getChatMessages(chatId).some((msg) => msg?.from === 'in' && msg?.unread);
const UNREAD_SEPARATOR_AUTO_HIDE_MS = 5000;
let historyHasMore = true;
@@ -1151,44 +1153,59 @@ export function render({ navigate, route, chrome }) {
chatHeaderLeft?.append(chatHeaderParts.avatarButton);
chrome?.setTopbar(chatHeader);
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 {
const approved = await openConfirmContactModal(chatId);
if (!approved) return;
await authService.setUserRelation({
login: state.session.login,
toLogin: chatId,
kind: 'contact',
enabled: true,
storagePwd: state.session.storagePwdInMemory,
});
const contactsPayload = await authService.listContacts();
setContacts(contactsPayload?.contacts || []);
addAppLogEntry({
level: 'info',
source: 'contacts',
message: `Пользователь ${chatId} добавлен в контакты`,
});
card.remove();
} catch (e) {
addAppLogEntry({
level: 'warn',
source: 'contacts',
message: 'Не удалось добавить пользователя в контакты',
details: { login: chatId, error: e?.message || 'unknown' },
});
}
const addContactCard = document.createElement('div');
addContactCard.className = 'card dm-add-contact-card';
addContactCard.hidden = true;
const addContactBtn = document.createElement('button');
addContactBtn.className = 'secondary-btn';
addContactBtn.type = 'button';
addContactBtn.textContent = 'Добавить собеседника в контакты';
addContactBtn.addEventListener('click', async () => {
try {
const approved = await openConfirmContactModal(chatId);
if (!approved) return;
await authService.setUserRelation({
login: state.session.login,
toLogin: chatId,
kind: 'contact',
enabled: true,
storagePwd: state.session.storagePwdInMemory,
});
const contactsPayload = await authService.listContacts();
setContacts(contactsPayload?.contacts || []);
addAppLogEntry({
level: 'info',
source: 'contacts',
message: `Пользователь ${chatId} добавлен в контакты`,
});
addContactCard.remove();
} catch (e) {
addAppLogEntry({
level: 'warn',
source: 'contacts',
message: 'Не удалось добавить пользователя в контакты',
details: { login: chatId, error: e?.message || 'unknown' },
});
}
});
addContactCard.append(addContactBtn);
log.prepend(addContactCard);
// The button is valid only when there is no social relation at all.
// listContacts already returns relationFlag for every dialog/peer, so no extra server API is needed.
void authService.listContacts()
.then((contactsPayload) => {
setContacts(contactsPayload?.contacts || []);
const peerKey = String(chatId || '').trim().toLowerCase();
const peerDialog = (Array.isArray(contactsPayload?.dialogs) ? contactsPayload.dialogs : [])
.find((dialog) => String(dialog?.peerLogin || '').trim().toLowerCase() === peerKey);
const relationFlag = String(peerDialog?.relationFlag || 'none').trim().toLowerCase();
addContactCard.hidden = relationFlag !== 'none';
})
.catch(() => {
// On an API failure do not offer a potentially invalid relation action.
addContactCard.hidden = true;
});
card.append(btn);
screen.append(card);
}
const form = document.createElement('form');
form.className = 'chat-input dm-chat-input';
+1 -1
View File
@@ -319,7 +319,7 @@ function renderRow(item) {
const titleEl = row.querySelector('.dm-row-title');
const previewEl = row.querySelector('.dm-row-last-message');
const timeEl = row.querySelector('.dm-row-time');
if (titleEl) titleEl.textContent = userDisplayName(item);
if (titleEl) titleEl.textContent = userDisplayName({ login: item.peerLogin, firstName: item.firstName, lastName: item.lastName });
if (previewEl) previewEl.textContent = 'Загрузка…';
if (timeEl) timeEl.textContent = formatChatRowTime(item.lastMessageTimeMs);
row.prepend(avatarWrap);