diff --git a/frontend/src/lib/components/MessageBubble.svelte b/frontend/src/lib/components/MessageBubble.svelte index 4ac411e..808af2c 100644 --- a/frontend/src/lib/components/MessageBubble.svelte +++ b/frontend/src/lib/components/MessageBubble.svelte @@ -18,11 +18,14 @@ import Icon from "#lib/components/ui/Icon.svelte"; import WebPage from "#lib/components/WebPage.svelte"; import { accountName, peerColorIndex, peerName } from "#lib/format/peer.js"; + import { t } from "#lib/i18n/locale.svelte.js"; import { accounts } from "#lib/stores/accounts.svelte.js"; + import { chats } from "#lib/stores/chats.svelte.js"; import { peers } from "#lib/stores/peers.svelte.js"; import { toasts } from "#lib/stores/toasts.svelte.js"; import { ui } from "#lib/stores/ui.svelte.js"; import { appear } from "#lib/transitions/appear.js"; + import { goto } from "$app/navigation"; interface Props { animate: boolean; @@ -59,27 +62,47 @@ ); const ownId = $derived(accounts.selected?.tg_user_id ?? null); + const senderChat = $derived( + message.sender_id !== null && message.sender_id < 0 + ? message.sender_id + : null + ); const sender = $derived( - message.sender_id === null ? undefined : peers.get(message.sender_id) + message.sender_id === null || senderChat !== null + ? undefined + : peers.get(message.sender_id) ); const senderName = $derived.by(() => { if (own) { - return accounts.selected ? accountName(accounts.selected) : "You"; + return accounts.selected ? accountName(accounts.selected) : t("chat.you"); + } + if (senderChat !== null) { + return chats.byId(senderChat)?.title ?? ""; } if (sender) { return peerName(sender); } return message.sender_id === null ? "" : String(message.sender_id); }); + + $effect(() => { + if (senderChat !== null) { + chats.ensure(senderChat); + } + }); const colorIndex = $derived(peerColorIndex(message.sender_id ?? 0)); const showName = $derived(isGroupChat && !own && firstInGroup); const avatarId = $derived(own ? ownId : message.sender_id); - const avatarHas = $derived( - own - ? ownId !== null && peers.get(ownId)?.has_avatar - : (sender?.has_avatar ?? false) - ); + const avatarHas = $derived.by(() => { + if (own) { + return ownId !== null && Boolean(peers.get(ownId)?.has_avatar); + } + if (senderChat !== null) { + return chats.byId(senderChat)?.has_avatar ?? false; + } + return sender?.has_avatar ?? false; + }); const hasCallbacks = $derived( message.inline_buttons.some((row) => @@ -116,14 +139,18 @@ } async function copyText() { await navigator.clipboard.writeText(message.text ?? ""); - toasts.success("Текст скопирован"); + toasts.success(t("thread.copiedText")); } async function copyId() { await navigator.clipboard.writeText(String(message.message_id)); - toasts.success("ID скопирован"); + toasts.success(t("thread.copiedId")); } function openSenderProfile() { - if (message.sender_id !== null) { + if (senderChat === message.chat_id) { + ui.openPanel("profile"); + } else if (senderChat !== null) { + goto(`/app/${senderChat}`); + } else if (message.sender_id !== null) { ui.openPerson(message.chat_id, message.sender_id); } } @@ -155,7 +182,10 @@ type="button" > - deleted + {t("thread.deleted")} {/if} {#if message.poll} @@ -218,7 +248,7 @@ /> {:else if !(message.has_media || deleted || special)} -
(no text)
+
{t("feed.noText")}
{/if} {#if message.web_page} @@ -233,8 +263,7 @@ {#if linkCount > 0} {/if} @@ -244,7 +273,7 @@ {#if hasCallbacks} {/if} {#if lastInGroup} @@ -263,42 +292,44 @@ {/if} Заметки{t("panel.annotations")} {#if message.reactions.length} Реакции{t("panel.reactions")} {/if} {#if linkCount > 0} - Ссылки + {t("panel.links")} {/if} {#if hasCallbacks} Callback-данные{t("panel.callbacks")} {/if} {#if message.edited_at} Версии{t("panel.versions")} {/if} {#if (message.reply?.message_id ?? null) !== null} Перейти к ответу{t("thread.toReply")} {/if} {#if hasText} Копировать текст{t("thread.copyText")} {/if} Копировать ID{t("thread.copyId")} {#if isGroupChat && !own && message.sender_id !== null} Профиль автора{t("thread.senderProfile")} {/if} {/snippet} diff --git a/frontend/src/lib/components/MessageList.svelte b/frontend/src/lib/components/MessageList.svelte index 199dfd6..77e2926 100644 --- a/frontend/src/lib/components/MessageList.svelte +++ b/frontend/src/lib/components/MessageList.svelte @@ -14,6 +14,8 @@ import { formatDay } from "#lib/format/datetime.js"; import { t } from "#lib/i18n/locale.svelte.js"; import { accounts } from "#lib/stores/accounts.svelte.js"; + import { chats } from "#lib/stores/chats.svelte.js"; + import { discover } from "#lib/stores/discover.svelte.js"; import { events } from "#lib/stores/events.svelte.js"; import { peers } from "#lib/stores/peers.svelte.js"; import { toasts } from "#lib/stores/toasts.svelte.js"; @@ -54,7 +56,11 @@ let highlightTimer: ReturnType | null = null; const ownId = $derived(accounts.selected?.tg_user_id ?? null); - const isGroupChat = $derived(chatId < 0); + const isChannel = $derived( + Boolean(chats.byId(chatId)?.is_broadcast) || + discover.get(chatId)?.kind === "channel" + ); + const isGroupChat = $derived(chatId < 0 && !isChannel); interface Row { dayKey: string;