feat(chat): ответы на сообщения с цитатой и переходом к оригиналу
Кнопка «Ответить» у каждого сообщения: цитата показывается в новом сообщении и в поле ввода, отмена — ✕ или Escape, переключение треда сбрасывает ответ. Клик по цитате прокручивает ленту к исходному сообщению и подсвечивает его. Цитата повторяет вложение оригинала: имя файла с иконкой, для картинок — миниатюра WebP через существующий /api/chat/files/:token. - chat_messages.reply_to_id: FK на саму таблицу с ON DELETE SET NULL, миграция и ensureChatTables, индекс - POST .../messages принимает reply_to_id и проверяет, что родитель в этом же треде и не удалён; вложения при ошибке подчищаются - цитата едет в списке, при отправке и в SSE правки/удаления, так что у собеседника она обновляется по живому каналу - бэкап: reply_to_id в normalizeRestoreData, при restore ссылка принимается только если родитель восстановился, иначе NULL - shorts: скрывать поле «Резидент» при добавлении без разбора строк
This commit is contained in:
+24
-1
@@ -982,7 +982,18 @@ body.report-card-open .report-fields{display:flex}
|
||||
.msg-act:hover{color:var(--accent);background:var(--bg)}
|
||||
.msg-act-del:hover{color:#ef4444}
|
||||
.msg-act svg{width:13px;height:13px}
|
||||
.msg-deleted-body{font-style:italic;color:var(--muted)}
|
||||
.msg-reply{display:flex;flex-direction:column;gap:1px;border-left:2px solid var(--accent);background:var(--bg);border-radius:0 7px 7px 0;padding:4px 8px;margin-bottom:2px;min-width:0;text-align:left;font:inherit;cursor:pointer;position:relative}
|
||||
.msg-reply:hover{background:var(--card);border-left-color:var(--accent)}
|
||||
.msg-reply-img{display:block;width:100%;max-width:280px;max-height:150px;object-fit:cover;border-radius:6px;background:var(--card);margin-bottom:4px}
|
||||
.msg-reply-who{font-size:.68rem;color:var(--accent);font-weight:600}
|
||||
.msg-reply-text{font-size:.75rem;color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:280px}
|
||||
.msg-reply-text[hidden]{display:none}
|
||||
.msg-reply-file{display:inline-flex;align-items:center;gap:5px;font-size:.75rem;color:var(--muted);max-width:280px;min-width:0}
|
||||
.msg-reply-file[hidden]{display:none}
|
||||
.msg-reply-file svg{width:13px;height:13px;flex-shrink:0}
|
||||
.msg-reply-file span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.msg-flash{animation:msgFlash 1.4s ease-out}
|
||||
@keyframes msgFlash{0%,100%{box-shadow:none}12%,55%{box-shadow:0 0 0 3px rgba(37,99,235,.35)}}
|
||||
.chat-edit-modal{max-width:560px}
|
||||
.chat-edit-modal textarea{min-height:110px;max-height:40dvh}
|
||||
.chat-edit-modal textarea:focus{border-color:var(--accent)}
|
||||
@@ -997,6 +1008,18 @@ body.report-card-open .report-fields{display:flex}
|
||||
.msg-file-img img{width:100%;height:110px;object-fit:cover;border-radius:6px;display:block;background:var(--bg)}
|
||||
.msg-file-img .msg-file-name{font-size:.7rem;color:var(--muted)}
|
||||
.chat-composer{border-top:1px solid var(--border);padding:11px 14px 13px;display:flex;flex-direction:column;gap:8px}
|
||||
.chat-reply-bar{display:flex;align-items:center;gap:8px;background:var(--bg);border:1px solid var(--accent);border-radius:9px;padding:6px 9px;font-size:.78rem}
|
||||
.chat-reply-bar[hidden]{display:none}
|
||||
.chat-reply-bar svg{width:14px;height:14px;color:var(--accent);flex-shrink:0}
|
||||
.chat-reply-meta{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
|
||||
.chat-reply-who{color:var(--accent);font-weight:600;font-size:.7rem}
|
||||
.chat-reply-text{color:var(--muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.chat-reply-text[hidden]{display:none}
|
||||
.chat-reply-file{display:inline-flex;align-items:center;gap:5px;color:var(--muted);min-width:0}
|
||||
.chat-reply-file[hidden]{display:none}
|
||||
.chat-reply-img{display:block;height:44px;width:44px;object-fit:cover;border-radius:6px;background:var(--card);flex-shrink:0}
|
||||
.chat-reply-file svg{width:13px;height:13px;flex-shrink:0}
|
||||
.chat-reply-file span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
||||
.chat-attach-list{display:flex;flex-wrap:wrap;gap:7px}
|
||||
.chat-attach-list[hidden]{display:none}
|
||||
.chat-attach-chip{display:inline-flex;align-items:center;gap:6px;background:var(--bg);border:1px solid var(--border);border-radius:8px;padding:5px 9px;font-size:.75rem;max-width:250px}
|
||||
|
||||
Reference in New Issue
Block a user