Fix: исправлена загрузка видео и стилизация вложений

Исправление видео:
- Видео элементы создаются с уникальными ID
- src устанавливается после добавления в DOM через requestAnimationFrame
- Используется preload='auto' вместо 'metadata' для немедленной загрузки
- video.load() вызывается после установки src

Стилизация вложений:
- Убран bg-light у ссылок на файлы
- Добавлены стили .message-attachments для прозрачного фона
- Для bubble-me используется rgba(255,255,255,0.15) фон
- Для обычных сообщений используется rgba(0,0,0,0.05) фон
- Добавлены hover эффекты
- Файлы теперь соответствуют цвету сообщения
This commit is contained in:
admin i 2025-11-28 08:19:15 +03:00
parent eae685eacf
commit 91bc8386a1
3 changed files with 58 additions and 39 deletions

View File

@ -231,6 +231,43 @@ main.main {
opacity: 1;
}
/* Вложения в сообщениях */
.message-attachments {
margin-top: 8px;
}
.message-attachments .attachment-item {
background: transparent !important;
padding: 0;
margin-bottom: 8px;
}
.message-attachments a {
background: rgba(0, 0, 0, 0.05);
border: 1px solid rgba(0, 0, 0, 0.08);
transition: all 0.2s ease;
}
.bubble-me .message-attachments a {
background: rgba(255, 255, 255, 0.15);
border-color: rgba(255, 255, 255, 0.2);
}
.message-attachments a:hover {
background: rgba(0, 0, 0, 0.08);
}
.bubble-me .message-attachments a:hover {
background: rgba(255, 255, 255, 0.25);
}
.message-attachments video,
.message-attachments img,
.message-attachments audio {
max-width: 100%;
border-radius: 8px;
}
/* Выпадающее меню вложений */
.dropdown-menu {
min-width: 200px;

View File

@ -155,9 +155,10 @@ export function createMessageElement(msg, options = {}) {
// Формирование вложений
let attachmentsHTML = '';
let videoIds = [];
if (msg.has_attachments && msg.attachments && msg.attachments.length > 0) {
attachmentsHTML = '<div class="message-attachments mt-2">';
msg.attachments.forEach(att => {
msg.attachments.forEach((att, index) => {
attachmentsHTML += '<div class="attachment-item mb-2">';
if (att.file_type === 'image') {
@ -175,9 +176,11 @@ export function createMessageElement(msg, options = {}) {
</audio>
<div class="small text-secondary">${esc(att.file_name)}</div>`;
} else if (att.file_type === 'video') {
const videoId = `video_${Date.now()}_${index}`;
videoIds.push({ id: videoId, url: att.file_url, mime: att.mime_type });
attachmentsHTML += `
<video controls preload="metadata" class="w-100" style="max-width: 400px;">
<source src="${att.file_url}" type="${att.mime_type}">
<video id="${videoId}" controls preload="auto" class="w-100" style="max-width: 400px;">
<source type="${att.mime_type}">
Ваш браузер не поддерживает видео.
</video>
<div class="small text-secondary">${esc(att.file_name)}</div>`;
@ -185,7 +188,7 @@ export function createMessageElement(msg, options = {}) {
const fileSize = att.file_size ? formatFileSize(att.file_size) : '';
attachmentsHTML += `
<a href="${att.file_url}"
class="d-flex align-items-center text-decoration-none p-2 border rounded bg-light"
class="d-flex align-items-center text-decoration-none p-2 border rounded"
download="${esc(att.file_name)}">
<i class="bi-file-earmark fs-3 text-primary me-2"></i>
<div>
@ -223,41 +226,20 @@ export function createMessageElement(msg, options = {}) {
wrap.innerHTML = `${bubble}<a class="ms-2 text-decoration-none" href="${profileUrl}">${ava}</a>`;
}
// Принудительно создаём и загружаем видео элементы после добавления в DOM
if (msg.has_attachments && msg.attachments && msg.attachments.length > 0) {
// Находим все video placeholder'ы и заменяем их реальными элементами
const videoContainers = wrap.querySelectorAll('.attachment-item');
msg.attachments.forEach((att, index) => {
if (att.file_type === 'video') {
const container = videoContainers[index];
if (container) {
// Очищаем контейнер
container.innerHTML = '';
// Создаём video элемент программно
const video = document.createElement('video');
video.controls = true;
video.preload = 'metadata';
video.className = 'w-100';
video.style.maxWidth = '400px';
const source = document.createElement('source');
source.src = att.file_url;
source.type = att.mime_type;
video.appendChild(source);
const textDiv = document.createElement('div');
textDiv.className = 'small text-secondary';
textDiv.textContent = att.file_name;
container.appendChild(video);
container.appendChild(textDiv);
// Загружаем видео
video.load();
// Устанавливаем src для видео после добавления в DOM
if (videoIds.length > 0) {
// Используем requestAnimationFrame чтобы убедиться что элементы в DOM
requestAnimationFrame(() => {
videoIds.forEach(videoData => {
const video = wrap.querySelector(`#${videoData.id}`);
if (video) {
const source = video.querySelector('source');
if (source) {
source.src = videoData.url;
video.load();
}
}
}
});
});
}

View File

@ -114,7 +114,7 @@
<div class="small text-secondary">{{ attachment.file_name }}</div>
{% else %}
<a href="{{ attachment.file.url }}"
class="d-flex align-items-center text-decoration-none p-2 border rounded bg-light"
class="d-flex align-items-center text-decoration-none p-2 border rounded"
download="{{ attachment.file_name }}">
<i class="bi-file-earmark fs-3 text-primary me-2"></i>
<div>