fix(dm): Ctrl+Enter перенос, время в списке и выравнивание карточек

This commit is contained in:
AidarKC 2026-05-19 16:13:44 +03:00
parent 8325cbec84
commit 9c35567389
5 changed files with 84 additions and 8 deletions

View File

@ -0,0 +1,28 @@
# DM: Ctrl+Enter, автоскролл и время в списке
- Статус: `pending`
## Что сделано
- Исправлено поведение ввода в чате:
- `Enter` отправляет сообщение;
- `Ctrl+Enter` добавляет перенос строки в поле ввода.
- В списке личных сообщений время последнего сообщения всегда отображается в правой колонке снизу.
- Бейдж непрочитанных сообщений (если есть) отображается над временем, не заменяя его.
- Обновлены стили карточки диалога для компактного и стабильного выравнивания.
## Что проверять
- В чате:
- нажать `Ctrl+Enter` в середине текста и убедиться, что вставляется новая строка;
- нажать `Enter` и убедиться, что сообщение отправляется.
- В списке диалогов:
- при `unread=0` справа снизу показывается время;
- при `unread>0` сверху бейдж, снизу всё равно показывается время;
- длинный текст последнего сообщения обрезается многоточием и не наезжает на время.
## Ожидаемый результат
- Управление вводом работает как в постановке.
- Время в карточке диалога не исчезает при наличии непрочитанных сообщений.
- Верстка карточки остаётся компактной и без сдвигов.

View File

@ -1,2 +1,2 @@
client.version=1.2.72
server.version=1.2.66
client.version=1.2.73
server.version=1.2.67

View File

@ -418,7 +418,21 @@ export function render({ navigate, route }) {
input?.addEventListener('input', () => autoResizeComposer(input));
input?.addEventListener('keydown', async (event) => {
if (event.key !== 'Enter') return;
if (event.ctrlKey) return;
if (event.ctrlKey) {
event.preventDefault();
const start = Number(input.selectionStart ?? input.value.length);
const end = Number(input.selectionEnd ?? input.value.length);
const value = String(input.value || '');
input.value = `${value.slice(0, start)}\n${value.slice(end)}`;
const nextPos = start + 1;
try {
input.setSelectionRange(nextPos, nextPos);
} catch {
// ignore
}
autoResizeComposer(input);
return;
}
event.preventDefault();
const text = String(input.value || '').trim();
if (!text) return;

View File

@ -42,12 +42,12 @@ export function render({ navigate }) {
row.className = 'list-item dm-dialog-card';
row.innerHTML = `
<div class="avatar">${item.initials}</div>
<div>
<div class="row" style="justify-content:flex-start; gap:8px;">
<strong>${item.name}</strong>
<div class="dm-row-main">
<div class="dm-row-title-wrap">
<strong class="dm-row-title">${item.name}</strong>
${item.notInContacts ? '<span class="meta-muted">не в контактах</span>' : ''}
</div>
<p class="meta-muted" style="margin-top:4px;">${item.lastMessage}</p>
<p class="meta-muted dm-row-last-message">${item.lastMessage}</p>
</div>
<div class="dm-row-meta-col">
${item.unread ? `<span class="unread">${item.unread}</span>` : '<span></span>'}

View File

@ -3405,6 +3405,10 @@ textarea.input {
font-weight: 700;
}
.dm-screen .list-item {
align-items: stretch;
}
.dm-screen .meta-muted {
color: rgba(255, 255, 255, 0.5);
}
@ -3430,14 +3434,44 @@ textarea.input {
.dm-row-meta-col {
display: grid;
justify-items: end;
align-content: start;
align-content: end;
gap: 6px;
min-width: 64px;
align-self: stretch;
}
.dm-row-main {
min-width: 0;
display: grid;
grid-template-rows: auto auto;
gap: 4px;
}
.dm-row-title-wrap {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
}
.dm-row-title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.dm-row-last-message {
margin-top: 0 !important;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding-right: 6px;
}
.dm-row-time {
font-size: 11px;
line-height: 1.2;
white-space: nowrap;
}
.dm-chat-wrap {