Чат: поиск сверху, метка бота в списке ЛС, галочка закрытых разговоров

- Строка поиска перенесена наверх страницы (над всем чатом), результаты
  по-прежнему открываются в области сообщений
- В списке ЛС у собеседников-ботов рядом выводится метка «бот»
- Закрытые/архивные разговоры (delete_at>0) скрыты по умолчанию, показываются
  только по галочке «Показувати закриті розмови» (тянем include_deleted=true)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 21:36:18 +03:00
parent 97bf274c6b
commit 5181c2f2ab
2 changed files with 61 additions and 16 deletions
+44 -7
View File
@@ -28,6 +28,17 @@ var chatCurrentTeamId = null; // обрана «кімната» (кома
var chatDmOtherUserId = {}; // channelId -> id співрозмовника (для аватара ЛС)
var chatUnread = {}; // channelId -> к-сть непрочитаних
var chatLastActivity = {}; // channelId -> час останнього поста (мс)
var chatShowArchived = false; // показувати закриті/архівні розмови
function chatIsArchived(ch) {
return !!(ch && ch.delete_at && ch.delete_at > 0);
}
function chatToggleArchived(show) {
chatShowArchived = !!show;
chatRenderChannelList();
chatRenderDmList();
}
function chatPanelOpen(id) {
var panel = document.getElementById(id);
@@ -81,6 +92,7 @@ function chatInit() {
chatDmOtherUserId = {};
chatUnread = {};
chatLastActivity = {};
chatShowArchived = false;
chatLoadTeams().then(chatLoadChannels).then(chatOpenPendingDm);
chatConnectSocket();
@@ -241,7 +253,8 @@ function chatByRecent(a, b) {
}
function chatLoadChannels() {
return chatApiFetch('/users/me/channels').then(function (channels) {
// include_deleted=true — щоб мати закриті/архівні розмови (ховаємо їх за галочкою).
return chatApiFetch('/users/me/channels?include_deleted=true').then(function (channels) {
chatChannels = channels
.filter(function (ch) { return ch.type === 'O' || ch.type === 'P'; })
.sort(chatByRecent);
@@ -326,6 +339,16 @@ function chatResolveDmLabel(channel) {
if (otherId) chatApplyAvatar(avEl, otherId); // фото — лише для особистих (не групових)
}
if (chatCurrentChannelId === channel.id) chatUpdateHeader(channel);
// Позначка «бот» у списку ЛС, якщо співрозмовник — бот (стало відомо після resolve).
if (otherId && chatUserIsBot[otherId] && !document.getElementById('chat-dm-bot-' + channel.id)) {
var row = document.getElementById('chat-channel-row-' + channel.id);
if (row) {
var b = chatBotBadge();
b.id = 'chat-dm-bot-' + channel.id;
b.style.flexShrink = '0';
row.appendChild(b);
}
}
}).catch(function (e) { console.error(e); });
}
@@ -334,7 +357,8 @@ function chatRenderChannelList() {
if (!el) return;
var list = chatChannels.filter(function (ch) {
return !chatCurrentTeamId || ch.team_id === chatCurrentTeamId;
return (!chatCurrentTeamId || ch.team_id === chatCurrentTeamId)
&& (chatShowArchived || !chatIsArchived(ch));
});
if (!list.length) {
@@ -354,19 +378,25 @@ function chatRenderDmList() {
var el = document.getElementById('chat-dm-list');
if (!el) return;
if (!chatDmChannels.length) {
var list = chatDmChannels.filter(function (ch) {
return chatShowArchived || !chatIsArchived(ch);
});
if (!list.length) {
el.innerHTML = '<div style="padding:0.75rem; text-align:center; font-size:0.75rem; color:var(--color-muted-foreground);">Немає повідомлень</div>';
return;
}
el.innerHTML = '';
chatDmChannels.forEach(function (ch) {
list.forEach(function (ch) {
var otherId = chatDmOtherUserId[ch.id];
var isBot = ch.type === 'D' && otherId && chatUserIsBot[otherId];
var row = chatBuildChannelRow(ch.id, chatDmLabels[ch.id] || '…',
ch.type === 'G' ? 'Групова розмова' : '', {avatar: true});
ch.type === 'G' ? 'Групова розмова' : '', {avatar: true, bot: isBot});
el.appendChild(row);
// Якщо співрозмовник ЛС уже відомий — одразу показати його аватар.
if (ch.type === 'D' && chatDmOtherUserId[ch.id]) {
chatApplyAvatar(document.getElementById('chat-dm-avatar-' + ch.id), chatDmOtherUserId[ch.id]);
if (ch.type === 'D' && otherId) {
chatApplyAvatar(document.getElementById('chat-dm-avatar-' + ch.id), otherId);
}
});
}
@@ -408,6 +438,13 @@ function chatBuildChannelRow(channelId, label, subLabel, opts) {
row.appendChild(textCol);
if (opts.bot) {
var botMark = chatBotBadge();
botMark.id = 'chat-dm-bot-' + channelId;
botMark.style.flexShrink = '0';
row.appendChild(botMark);
}
var unread = chatUnread[channelId] || 0;
if (unread > 0) {
name.style.fontWeight = '700';