From 479fe3e0d7f2351066c657c1e6b7cea7adf77b52 Mon Sep 17 00:00:00 2001 From: lokses Date: Fri, 24 Jul 2026 17:10:09 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A7=D0=B0=D1=82:=20=D0=B0=D0=B2=D0=B0=D1=82?= =?UTF-8?q?=D0=B0=D1=80=D1=8B-=D1=84=D0=BE=D1=82=D0=BE=20=D1=81=D0=BE?= =?UTF-8?q?=D1=82=D1=80=D1=83=D0=B4=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=20=D0=B8?= =?UTF-8?q?=20=D0=B1=D0=BE=D1=82=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - chatApplyAvatar(el, userId): подгружает фото из Mattermost /users/{id}/image (работает и для сотрудников, и для ботов) и накладывает на кружок-аватар; до загрузки/при ошибке остаются инициалы. Кэш по userId. - Применено в сообщениях (chatBuildMessageEl) и в пикере коллег (chatRenderDmPickerList) - Переиспользует существующий chatApiFetchBlob (Bearer-токен) Co-Authored-By: Claude Opus 4.8 --- static/assets/js/chat.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/static/assets/js/chat.js b/static/assets/js/chat.js index 34ba850..61136a7 100644 --- a/static/assets/js/chat.js +++ b/static/assets/js/chat.js @@ -92,6 +92,28 @@ function chatApiFetchBlob(path) { }); } +var chatAvatarCache = {}; // userId -> objectURL профільного фото (юзери і боти) + +// Підвантажує аватар користувача/бота з Mattermost (/users/{id}/image) і +// накладає його на елемент-кружок. Поки фото не завантажилось (або якщо +// сталася помилка) лишаються ініціали, вже намальовані на елементі. +function chatApplyAvatar(el, userId) { + if (!el || !userId) return; + el.style.position = 'relative'; + el.style.overflow = 'hidden'; + var img = document.createElement('img'); + img.alt = ''; + img.style.cssText = 'position:absolute; inset:0; width:100%; height:100%; object-fit:cover; opacity:0; transition:opacity 150ms;'; + img.onload = function () { img.style.opacity = '1'; }; + el.appendChild(img); + if (chatAvatarCache[userId]) { img.src = chatAvatarCache[userId]; return; } + chatApiFetchBlob('/users/' + userId + '/image').then(function (blob) { + var url = URL.createObjectURL(blob); + chatAvatarCache[userId] = url; + img.src = url; + }).catch(function () { /* лишаємо ініціали */ }); +} + function chatResolveUserIds(ids) { var missing = ids.filter(function (id) { return id && !chatUserNames[id]; }); missing = missing.filter(function (id, i) { return missing.indexOf(id) === i; }); @@ -314,6 +336,7 @@ function chatBuildMessageEl(post, context) { avatar.style.cssText = 'width:2rem; height:2rem; border-radius:50%; background:hsl(205 80% 55% / 0.15); color:hsl(205 80% 45%); display:flex; align-items:center; justify-content:center; font-size:0.625rem; font-weight:700; flex-shrink:0;'; var senderName = chatUserNames[post.user_id] || post.user_id; avatar.textContent = senderName.slice(0, 2).toUpperCase(); + chatApplyAvatar(avatar, post.user_id); wrap.appendChild(avatar); var body = document.createElement('div'); @@ -709,6 +732,11 @@ function chatRenderDmPickerList() { } }; row.appendChild(checkbox); + var av = document.createElement('div'); + av.style.cssText = 'width:1.75rem; height:1.75rem; border-radius:50%; background:hsl(205 80% 55% / 0.15); color:hsl(205 80% 45%); display:flex; align-items:center; justify-content:center; font-size:0.5625rem; font-weight:700; flex-shrink:0;'; + av.textContent = c.name.slice(0, 2).toUpperCase(); + chatApplyAvatar(av, c.mattermostId); + row.appendChild(av); var name = document.createElement('span'); name.textContent = c.name; row.appendChild(name);