fix(frontend): channel posts show no sender id, a post sent as a chat shows its title and avatar

This commit is contained in:
hh committed 2026-10-19 03:25:48 +00:00
1 parent 98dda99c5c
commit 309614c979
2 files changed
+63 -26

No files matched your search

@@ -18,11 +18,14 @@
import Icon from "#lib/components/ui/Icon.svelte"; import Icon from "#lib/components/ui/Icon.svelte";
import WebPage from "#lib/components/WebPage.svelte"; import WebPage from "#lib/components/WebPage.svelte";
import { accountName, peerColorIndex, peerName } from "#lib/format/peer.js"; 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 { accounts } from "#lib/stores/accounts.svelte.js";
import { chats } from "#lib/stores/chats.svelte.js";
import { peers } from "#lib/stores/peers.svelte.js"; import { peers } from "#lib/stores/peers.svelte.js";
import { toasts } from "#lib/stores/toasts.svelte.js"; import { toasts } from "#lib/stores/toasts.svelte.js";
import { ui } from "#lib/stores/ui.svelte.js"; import { ui } from "#lib/stores/ui.svelte.js";
import { appear } from "#lib/transitions/appear.js"; import { appear } from "#lib/transitions/appear.js";
import { goto } from "$app/navigation";
interface Props { interface Props {
animate: boolean; animate: boolean;
@@ -59,27 +62,47 @@
); );
const ownId = $derived(accounts.selected?.tg_user_id ?? null); 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( 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(() => { const senderName = $derived.by(() => {
if (own) { 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) { if (sender) {
return peerName(sender); return peerName(sender);
} }
return message.sender_id === null ? "" : String(message.sender_id); 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 colorIndex = $derived(peerColorIndex(message.sender_id ?? 0));
const showName = $derived(isGroupChat && !own && firstInGroup); const showName = $derived(isGroupChat && !own && firstInGroup);
const avatarId = $derived(own ? ownId : message.sender_id); const avatarId = $derived(own ? ownId : message.sender_id);
const avatarHas = $derived( const avatarHas = $derived.by(() => {
own if (own) {
? ownId !== null && peers.get(ownId)?.has_avatar return ownId !== null && Boolean(peers.get(ownId)?.has_avatar);
: (sender?.has_avatar ?? false) }
); if (senderChat !== null) {
return chats.byId(senderChat)?.has_avatar ?? false;
}
return sender?.has_avatar ?? false;
});
const hasCallbacks = $derived( const hasCallbacks = $derived(
message.inline_buttons.some((row) => message.inline_buttons.some((row) =>
@@ -116,14 +139,18 @@
} }
async function copyText() { async function copyText() {
await navigator.clipboard.writeText(message.text ?? ""); await navigator.clipboard.writeText(message.text ?? "");
toasts.success("Текст скопирован"); toasts.success(t("thread.copiedText"));
} }
async function copyId() { async function copyId() {
await navigator.clipboard.writeText(String(message.message_id)); await navigator.clipboard.writeText(String(message.message_id));
toasts.success("ID скопирован"); toasts.success(t("thread.copiedId"));
} }
function openSenderProfile() { 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); ui.openPerson(message.chat_id, message.sender_id);
} }
} }
@@ -155,7 +182,10 @@
type="button" type="button"
> >
<Avatar <Avatar
avatar={{ id: avatarId, kind: "peer" }} avatar={{
id: avatarId,
kind: senderChat === null ? "peer" : "chat",
}}
colorKey={avatarId} colorKey={avatarId}
hasAvatar={avatarHas} hasAvatar={avatarHas}
name={senderName} name={senderName}
@@ -185,7 +215,7 @@
{#if deleted} {#if deleted}
<span class="deleted-tag"> <span class="deleted-tag">
<Icon name="delete" size="0.875rem" /> <Icon name="delete" size="0.875rem" />
deleted {t("thread.deleted")}
</span> </span>
{/if} {/if}
{#if message.poll} {#if message.poll}
@@ -218,7 +248,7 @@
/> />
</div> </div>
{:else if !(message.has_media || deleted || special)} {:else if !(message.has_media || deleted || special)}
<div class="text empty">(no text)</div> <div class="text empty">{t("feed.noText")}</div>
{/if} {/if}
{#if message.web_page} {#if message.web_page}
<WebPage {message} {onmedia} {own} /> <WebPage {message} {onmedia} {own} />
@@ -233,8 +263,7 @@
{#if linkCount > 0} {#if linkCount > 0}
<button class="detail-chip" onclick={openLinks} type="button"> <button class="detail-chip" onclick={openLinks} type="button">
<Icon name="link" size="0.875rem" /> <Icon name="link" size="0.875rem" />
{linkCount} {t("thread.links", { count: linkCount })}
{linkCount === 1 ? "ссылка" : "ссылки"}
</button> </button>
{/if} {/if}
<MessageMeta {message} {onversions} {own} /> <MessageMeta {message} {onversions} {own} />
@@ -244,7 +273,7 @@
{#if hasCallbacks} {#if hasCallbacks}
<button class="detail-chip" onclick={openCallbacks} type="button"> <button class="detail-chip" onclick={openCallbacks} type="button">
<Icon name="bot-command" size="0.875rem" /> <Icon name="bot-command" size="0.875rem" />
Callback-данные {t("panel.callbacks")}
</button> </button>
{/if} {/if}
{#if lastInGroup} {#if lastInGroup}
@@ -263,42 +292,44 @@
<MessageReadItem {message} /> <MessageReadItem {message} />
{/if} {/if}
<ContextMenuItem icon="note" onselect={openAnnotations} <ContextMenuItem icon="note" onselect={openAnnotations}
>Заметки</ContextMenuItem >{t("panel.annotations")}</ContextMenuItem
> >
{#if message.reactions.length} {#if message.reactions.length}
<ContextMenuItem icon="heart" onselect={openReactions} <ContextMenuItem icon="heart" onselect={openReactions}
>Реакции</ContextMenuItem >{t("panel.reactions")}</ContextMenuItem
> >
{/if} {/if}
{#if linkCount > 0} {#if linkCount > 0}
<ContextMenuItem icon="link" onselect={openLinks}>Ссылки</ContextMenuItem> <ContextMenuItem icon="link" onselect={openLinks}
>{t("panel.links")}</ContextMenuItem
>
{/if} {/if}
{#if hasCallbacks} {#if hasCallbacks}
<ContextMenuItem icon="bot-command" onselect={openCallbacks} <ContextMenuItem icon="bot-command" onselect={openCallbacks}
>Callback-данные</ContextMenuItem >{t("panel.callbacks")}</ContextMenuItem
> >
{/if} {/if}
{#if message.edited_at} {#if message.edited_at}
<ContextMenuItem icon="edit" onselect={onversions} <ContextMenuItem icon="edit" onselect={onversions}
>Версии</ContextMenuItem >{t("panel.versions")}</ContextMenuItem
> >
{/if} {/if}
{#if (message.reply?.message_id ?? null) !== null} {#if (message.reply?.message_id ?? null) !== null}
<ContextMenuItem icon="reply" onselect={jumpToReply} <ContextMenuItem icon="reply" onselect={jumpToReply}
>Перейти к ответу</ContextMenuItem >{t("thread.toReply")}</ContextMenuItem
> >
{/if} {/if}
{#if hasText} {#if hasText}
<ContextMenuItem icon="copy" onselect={copyText} <ContextMenuItem icon="copy" onselect={copyText}
>Копировать текст</ContextMenuItem >{t("thread.copyText")}</ContextMenuItem
> >
{/if} {/if}
<ContextMenuItem icon="hashtag" onselect={copyId} <ContextMenuItem icon="hashtag" onselect={copyId}
>Копировать ID</ContextMenuItem >{t("thread.copyId")}</ContextMenuItem
> >
{#if isGroupChat && !own && message.sender_id !== null} {#if isGroupChat && !own && message.sender_id !== null}
<ContextMenuItem icon="info" onselect={openSenderProfile} <ContextMenuItem icon="info" onselect={openSenderProfile}
>Профиль автора</ContextMenuItem >{t("thread.senderProfile")}</ContextMenuItem
> >
{/if} {/if}
{/snippet} {/snippet}
@@ -14,6 +14,8 @@
import { formatDay } from "#lib/format/datetime.js"; import { formatDay } from "#lib/format/datetime.js";
import { t } from "#lib/i18n/locale.svelte.js"; import { t } from "#lib/i18n/locale.svelte.js";
import { accounts } from "#lib/stores/accounts.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 { events } from "#lib/stores/events.svelte.js";
import { peers } from "#lib/stores/peers.svelte.js"; import { peers } from "#lib/stores/peers.svelte.js";
import { toasts } from "#lib/stores/toasts.svelte.js"; import { toasts } from "#lib/stores/toasts.svelte.js";
@@ -54,7 +56,11 @@
let highlightTimer: ReturnType<typeof setTimeout> | null = null; let highlightTimer: ReturnType<typeof setTimeout> | null = null;
const ownId = $derived(accounts.selected?.tg_user_id ?? 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 { interface Row {
dayKey: string; dayKey: string;