Merge remote-tracking branch 'origin/main'

This commit is contained in:
Weblate
2026-09-24 20:50:38 +00:00
5 changed files with 65 additions and 51 deletions
@@ -20,6 +20,10 @@ export function hasRichEmbedContent(embed: RichEmbedContentFields): boolean {
);
}
export function embedAllowsMarkdown(embed: Pick<MessageEmbed, 'type'>): boolean {
return embed.type === MessageEmbedTypes.RICH || embed.type === MessageEmbedTypes.BLUESKY;
}
type MediaOnlyEmbedFields = RichEmbedContentFields & Pick<MessageEmbed, 'image' | 'thumbnail' | 'video' | 'audio'>;
export function isMediaOnlyEmbed(embed: MediaOnlyEmbedFields): boolean {
@@ -205,6 +205,7 @@ export const BlueskyEmbed: FC<BlueskyEmbedProps> = observer(
<EmbedTitle
title={embed.title}
url={embed.url}
markdown
messageId={message.id}
channelId={message.channelId}
data-flx="channel.embeds.channel-embed.bluesky-embed.embed-title"
@@ -212,6 +213,7 @@ export const BlueskyEmbed: FC<BlueskyEmbedProps> = observer(
)}
<EmbedDescription
description={embed.description}
markdown
messageId={message.id}
channelId={message.channelId}
data-flx="channel.embeds.channel-embed.bluesky-embed.embed-description"
@@ -255,8 +257,6 @@ export const BlueskyEmbed: FC<BlueskyEmbedProps> = observer(
<EmbedFooterComponent
footer={embed.footer}
timestamp={embed.timestamp ? new Date(embed.timestamp) : undefined}
messageId={message.id}
channelId={message.channelId}
data-flx="channel.embeds.channel-embed.bluesky-embed.embed-footer-component"
/>
)}
@@ -69,47 +69,58 @@ export const EmbedAuthorComponent: FC<{author?: EmbedAuthor}> = observer(({autho
</div>
);
});
export const EmbedTitle: FC<{title?: string; url?: string; messageId?: string; channelId?: string}> = observer(
({title, url, messageId, channelId}) => {
if (title == null || title.length === 0) return null;
const options = {
context: MarkdownContext.RESTRICTED_INLINE_REPLY,
messageId,
channelId,
disableEmojiInteractions: Boolean(url),
};
return (
<div className={styles.embedTitle} data-flx="channel.embeds.embed.embed-title.embed-title">
{url ? (
<EmbedLink url={url} data-flx="channel.embeds.channel-embed.embed-parts.embed-title.embed-link">
<SafeMarkdown content={title} options={options} data-flx="channel.embeds.embed.embed-title.safe-markdown" />
</EmbedLink>
) : (
<span data-flx="channel.embeds.embed.embed-title.span">
<SafeMarkdown
content={title}
options={options}
data-flx="channel.embeds.embed.embed-title.safe-markdown--2"
/>
</span>
)}
</div>
);
},
);
export const EmbedTitle: FC<{
title?: string;
url?: string;
markdown: boolean;
messageId?: string;
channelId?: string;
}> = observer(({title, url, markdown, messageId, channelId}) => {
if (title == null || title.length === 0) return null;
const content = markdown ? (
<SafeMarkdown
content={title}
options={{
context: MarkdownContext.RESTRICTED_INLINE_REPLY,
messageId,
channelId,
disableEmojiInteractions: Boolean(url),
}}
data-flx="channel.embeds.embed.embed-title.safe-markdown"
/>
) : (
title
);
return (
<div className={styles.embedTitle} data-flx="channel.embeds.embed.embed-title.embed-title">
{url ? (
<EmbedLink url={url} data-flx="channel.embeds.channel-embed.embed-parts.embed-title.embed-link">
{content}
</EmbedLink>
) : (
<span data-flx="channel.embeds.embed.embed-title.span">{content}</span>
)}
</div>
);
});
export const EmbedDescription: FC<{
messageId?: string;
channelId?: string;
description?: string;
}> = observer(({messageId, channelId, description}) => {
markdown: boolean;
}> = observer(({messageId, channelId, description, markdown}) => {
if (!description) return null;
return (
<div className={styles.embedDescription} data-flx="channel.embeds.embed.embed-description.embed-description">
<SafeMarkdown
content={description}
options={{context: MarkdownContext.RESTRICTED_EMBED_DESCRIPTION, messageId, channelId}}
data-flx="channel.embeds.embed.embed-description.safe-markdown"
/>
{markdown ? (
<SafeMarkdown
content={description}
options={{context: MarkdownContext.RESTRICTED_EMBED_DESCRIPTION, messageId, channelId}}
data-flx="channel.embeds.embed.embed-description.safe-markdown"
/>
) : (
description
)}
</div>
);
});
@@ -182,9 +193,7 @@ export const EmbedFields: FC<{fields?: ReadonlyArray<EmbedField>; messageId?: st
export const EmbedFooterComponent: FC<{
timestamp?: Date;
footer?: EmbedFooter;
messageId?: string;
channelId?: string;
}> = observer(({timestamp, footer, messageId, channelId}) => {
}> = observer(({timestamp, footer}) => {
const {i18n} = useLingui();
const allowIconMotion = useShouldAnimate({kind: 'gif'});
const formattedTimestamp = timestamp ? DateUtils.getRelativeDateString(timestamp, i18n) : undefined;
@@ -206,13 +215,7 @@ export const EmbedFooterComponent: FC<{
/>
)}
<div className={styles.embedFooterText} data-flx="channel.embeds.embed.embed-footer-component.embed-footer-text">
{footer?.text && (
<SafeMarkdown
content={footer.text}
options={{context: MarkdownContext.RESTRICTED_INLINE_REPLY, messageId, channelId}}
data-flx="channel.embeds.embed.embed-footer-component.safe-markdown"
/>
)}
{footer?.text}
{formattedTimestamp && (
<>
{footer?.text && (
@@ -25,6 +25,7 @@ import {
} from '@app/features/channel/components/embeds/channel_embed/EmbedParts';
import {
EMBED_TEXT_OUTER_WIDTH,
embedAllowsMarkdown,
formatResponsiveEmbedWidth,
} from '@app/features/channel/components/embeds/EmbedRenderUtils';
import markupStyles from '@app/features/theme/styles/Markup.module.css';
@@ -83,6 +84,7 @@ export const RichEmbed: FC<EmbedProps> = observer(
<EmbedTitle
title={embed.title}
url={embed.url}
markdown={embedAllowsMarkdown(embed)}
messageId={message.id}
channelId={message.channelId}
data-flx="channel.embeds.channel-embed.rich-embed.embed-title"
@@ -90,6 +92,7 @@ export const RichEmbed: FC<EmbedProps> = observer(
{!isYouTubeEmbed && (
<EmbedDescription
description={embed.description}
markdown={embedAllowsMarkdown(embed)}
messageId={message.id}
channelId={message.channelId}
data-flx="channel.embeds.channel-embed.rich-embed.embed-description"
@@ -127,8 +130,6 @@ export const RichEmbed: FC<EmbedProps> = observer(
<EmbedFooterComponent
footer={embed.footer}
timestamp={embed.timestamp ? new Date(embed.timestamp) : undefined}
messageId={message.id}
channelId={message.channelId}
data-flx="channel.embeds.channel-embed.rich-embed.embed-footer-component"
/>
)}
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
import {embedAllowsMarkdown} from '@app/features/channel/components/embeds/EmbedRenderUtils';
import {MarkdownContext} from '@app/features/messaging/components/markdown/renderers/RendererTypes';
import type {Message} from '@app/features/messaging/models/MessagingMessage';
import {getParserFlagsForContext} from '@app/features/messaging/utils/markdown/MarkdownParserFlags';
@@ -193,8 +194,13 @@ export function buildMessageEmbedCopyText(embed: MessageEmbed, options: EmbedCop
const blocks: Array<string> = [];
appendCopyBlock(blocks, embed.provider?.name);
appendCopyBlock(blocks, embed.author?.name);
appendCopyBlock(blocks, renderMarkdownCopyText(embed.title, EMBED_INLINE_COPY_PARSER_FLAGS, options));
appendCopyBlock(blocks, renderMarkdownCopyText(embed.description, EMBED_DESCRIPTION_COPY_PARSER_FLAGS, options));
if (embedAllowsMarkdown(embed)) {
appendCopyBlock(blocks, renderMarkdownCopyText(embed.title, EMBED_INLINE_COPY_PARSER_FLAGS, options));
appendCopyBlock(blocks, renderMarkdownCopyText(embed.description, EMBED_DESCRIPTION_COPY_PARSER_FLAGS, options));
} else {
appendCopyBlock(blocks, embed.title);
appendCopyBlock(blocks, embed.description);
}
if (options.includeFields !== false && embed.type !== MessageEmbedTypes.BLUESKY) {
for (const field of embed.fields ?? []) {
const fieldName = renderMarkdownCopyText(field.name, EMBED_INLINE_COPY_PARSER_FLAGS, options);
@@ -202,7 +208,7 @@ export function buildMessageEmbedCopyText(embed: MessageEmbed, options: EmbedCop
appendCopyBlock(blocks, joinCopyBlocks([fieldName, fieldValue]));
}
}
appendCopyBlock(blocks, renderMarkdownCopyText(embed.footer?.text, EMBED_INLINE_COPY_PARSER_FLAGS, options));
appendCopyBlock(blocks, embed.footer?.text);
appendCopyBlock(blocks, getFormattedEmbedTimestamp(embed.timestamp));
appendCopyBlock(blocks, embed.image?.description);
appendCopyBlock(blocks, embed.thumbnail?.description);