fix(frontend): channel posts show no sender id, a post sent as a chat shows its title and avatar
This commit is contained in:
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;
|
||||||
|
|||||||
Reference in new issue
Block a user