Add buttons for t.me previews (#3068)
This commit is contained in:
parent
7e53d0da57
commit
1e36462ed7
@ -1133,33 +1133,6 @@ function buildAction(
|
||||
function buildReplyButtons(message: UniversalMessage, shouldSkipBuyButton?: boolean): ApiReplyKeyboard | undefined {
|
||||
const { replyMarkup, media } = message;
|
||||
|
||||
// TODO Move to the proper button inside preview
|
||||
if (!replyMarkup) {
|
||||
if (media instanceof GramJs.MessageMediaWebPage && media.webpage instanceof GramJs.WebPage) {
|
||||
if (media.webpage.type === 'telegram_message') {
|
||||
return {
|
||||
inlineButtons: [[{
|
||||
type: 'url',
|
||||
text: 'Show Message',
|
||||
url: media.webpage.url,
|
||||
}]],
|
||||
};
|
||||
}
|
||||
if (media.webpage.type === 'telegram_botapp') {
|
||||
return {
|
||||
inlineButtons: [[{
|
||||
type: 'url',
|
||||
text: 'Open App',
|
||||
url: media.webpage.url,
|
||||
}]],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// TODO
|
||||
if (!(replyMarkup instanceof GramJs.ReplyKeyboardMarkup || replyMarkup instanceof GramJs.ReplyInlineMarkup)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -1,22 +1,33 @@
|
||||
.WebPage {
|
||||
margin-top: 0.25rem;
|
||||
margin-bottom: 0.125rem;
|
||||
padding-left: 0.625rem;
|
||||
font-size: calc(var(--message-text-size, 1rem) - 0.125rem);
|
||||
line-height: 1.125rem;
|
||||
max-width: 29rem;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 0.125rem;
|
||||
background: var(--accent-color);
|
||||
border-radius: 0.125rem;
|
||||
.WebPage--content {
|
||||
padding-left: 0.625rem;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 0.125rem;
|
||||
background: var(--accent-color);
|
||||
border-radius: 0.125rem;
|
||||
}
|
||||
}
|
||||
|
||||
&--quick-button {
|
||||
margin-top: 0.375rem;
|
||||
|
||||
.theme-dark .Message.own &:hover {
|
||||
color: var(--background-color);
|
||||
}
|
||||
}
|
||||
|
||||
&-text {
|
||||
@ -55,13 +66,14 @@
|
||||
margin-bottom: 1rem !important;
|
||||
}
|
||||
|
||||
.message-content:not(.has-reactions) &.no-article:last-child {
|
||||
.message-content:not(.has-reactions) &.no-article:last-child,
|
||||
.message-content:not(.has-reactions) &.with-quick-button,
|
||||
.message-content:not(.has-reactions) &.with-square-photo {
|
||||
margin-bottom: 1rem !important;
|
||||
}
|
||||
|
||||
&.with-square-photo {
|
||||
&.with-square-photo .WebPage--content {
|
||||
display: flex;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
.WebPage-text {
|
||||
order: 1;
|
||||
@ -92,7 +104,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.with-square-photo) {
|
||||
&:not(.with-square-photo):not(.with-quick-button) {
|
||||
.site-name,
|
||||
.site-title,
|
||||
.site-description {
|
||||
|
||||
@ -1,20 +1,25 @@
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import React, { memo, useCallback } from '../../../lib/teact/teact';
|
||||
import { getActions } from '../../../global';
|
||||
|
||||
import type { FC } from '../../../lib/teact/teact';
|
||||
import type { ApiMessage } from '../../../api/types';
|
||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||
import type { ISettings } from '../../../types';
|
||||
|
||||
import { getMessageWebPage } from '../../../global/helpers';
|
||||
import { calculateMediaDimensions } from './helpers/mediaDimensions';
|
||||
import { getWebpageButtonText } from './helpers/webpageType';
|
||||
import renderText from '../../common/helpers/renderText';
|
||||
import trimText from '../../../util/trimText';
|
||||
import buildClassName from '../../../util/buildClassName';
|
||||
|
||||
import useAppLayout from '../../../hooks/useAppLayout';
|
||||
import useLang from '../../../hooks/useLang';
|
||||
|
||||
import SafeLink from '../../common/SafeLink';
|
||||
import Photo from './Photo';
|
||||
import Video from './Video';
|
||||
import Button from '../../ui/Button';
|
||||
|
||||
import './WebPage.scss';
|
||||
|
||||
@ -51,13 +56,23 @@ const WebPage: FC<OwnProps> = ({
|
||||
onMediaClick,
|
||||
onCancelMediaTransfer,
|
||||
}) => {
|
||||
const { openTelegramLink } = getActions();
|
||||
const webPage = getMessageWebPage(message);
|
||||
const { isMobile } = useAppLayout();
|
||||
|
||||
const lang = useLang();
|
||||
|
||||
const handleMediaClick = useCallback(() => {
|
||||
onMediaClick!();
|
||||
}, [onMediaClick]);
|
||||
|
||||
const handleQuickButtonClick = useCallback(() => {
|
||||
if (!webPage) return;
|
||||
openTelegramLink({
|
||||
url: webPage.url,
|
||||
});
|
||||
}, [webPage]);
|
||||
|
||||
if (!webPage) {
|
||||
return undefined;
|
||||
}
|
||||
@ -70,7 +85,9 @@ const WebPage: FC<OwnProps> = ({
|
||||
description,
|
||||
photo,
|
||||
video,
|
||||
type,
|
||||
} = webPage;
|
||||
const quickButtonLangKey = !inPreview ? getWebpageButtonText(type) : undefined;
|
||||
const truncatedDescription = trimText(description, MAX_TEXT_LENGTH);
|
||||
const isArticle = Boolean(truncatedDescription || title || siteName);
|
||||
let isSquarePhoto = false;
|
||||
@ -87,56 +104,73 @@ const WebPage: FC<OwnProps> = ({
|
||||
!photo && !video && !inPreview && 'without-media',
|
||||
video && 'with-video',
|
||||
!isArticle && 'no-article',
|
||||
quickButtonLangKey && 'with-quick-button',
|
||||
);
|
||||
|
||||
function renderQuickButton(langKey: string) {
|
||||
return (
|
||||
<Button
|
||||
className="WebPage--quick-button"
|
||||
size="tiny"
|
||||
color="translucent-bordered"
|
||||
onClick={handleQuickButtonClick}
|
||||
>
|
||||
{lang(langKey)}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
data-initial={(siteName || displayUrl)[0]}
|
||||
dir="auto"
|
||||
>
|
||||
{photo && !video && (
|
||||
<Photo
|
||||
message={message}
|
||||
observeIntersection={observeIntersection}
|
||||
noAvatars={noAvatars}
|
||||
canAutoLoad={canAutoLoad}
|
||||
size={isSquarePhoto ? 'pictogram' : 'inline'}
|
||||
asForwarded={asForwarded}
|
||||
nonInteractive={!isMediaInteractive}
|
||||
isDownloading={isDownloading}
|
||||
isProtected={isProtected}
|
||||
theme={theme}
|
||||
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
||||
onCancelUpload={onCancelMediaTransfer}
|
||||
/>
|
||||
)}
|
||||
{isArticle && (
|
||||
<div className="WebPage-text">
|
||||
<SafeLink className="site-name" url={url} text={siteName || displayUrl} />
|
||||
{!inPreview && title && (
|
||||
<p className="site-title">{renderText(title)}</p>
|
||||
)}
|
||||
{truncatedDescription && (
|
||||
<p className="site-description">{renderText(truncatedDescription, ['emoji', 'br'])}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{!inPreview && video && (
|
||||
<Video
|
||||
message={message}
|
||||
observeIntersectionForLoading={observeIntersection!}
|
||||
noAvatars={noAvatars}
|
||||
canAutoLoad={canAutoLoad}
|
||||
canAutoPlay={canAutoPlay}
|
||||
lastSyncTime={lastSyncTime}
|
||||
asForwarded={asForwarded}
|
||||
isDownloading={isDownloading}
|
||||
isProtected={isProtected}
|
||||
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
||||
onCancelUpload={onCancelMediaTransfer}
|
||||
/>
|
||||
)}
|
||||
<div className="WebPage--content">
|
||||
{photo && !video && (
|
||||
<Photo
|
||||
message={message}
|
||||
observeIntersection={observeIntersection}
|
||||
noAvatars={noAvatars}
|
||||
canAutoLoad={canAutoLoad}
|
||||
size={isSquarePhoto ? 'pictogram' : 'inline'}
|
||||
asForwarded={asForwarded}
|
||||
nonInteractive={!isMediaInteractive}
|
||||
isDownloading={isDownloading}
|
||||
isProtected={isProtected}
|
||||
theme={theme}
|
||||
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
||||
onCancelUpload={onCancelMediaTransfer}
|
||||
/>
|
||||
)}
|
||||
{isArticle && (
|
||||
<div className="WebPage-text">
|
||||
<SafeLink className="site-name" url={url} text={siteName || displayUrl} />
|
||||
{!inPreview && title && (
|
||||
<p className="site-title">{renderText(title)}</p>
|
||||
)}
|
||||
{truncatedDescription && (
|
||||
<p className="site-description">{renderText(truncatedDescription, ['emoji', 'br'])}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{!inPreview && video && (
|
||||
<Video
|
||||
message={message}
|
||||
observeIntersectionForLoading={observeIntersection!}
|
||||
noAvatars={noAvatars}
|
||||
canAutoLoad={canAutoLoad}
|
||||
canAutoPlay={canAutoPlay}
|
||||
lastSyncTime={lastSyncTime}
|
||||
asForwarded={asForwarded}
|
||||
isDownloading={isDownloading}
|
||||
isProtected={isProtected}
|
||||
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
||||
onCancelUpload={onCancelMediaTransfer}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{quickButtonLangKey && renderQuickButton(quickButtonLangKey)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
30
src/components/middle/message/helpers/webpageType.ts
Normal file
30
src/components/middle/message/helpers/webpageType.ts
Normal file
@ -0,0 +1,30 @@
|
||||
// https://github.com/telegramdesktop/tdesktop/blob/3da787791f6d227f69b32bf4003bc6071d05e2ac/Telegram/SourceFiles/history/view/history_view_view_button.cpp#L51
|
||||
export function getWebpageButtonText(type?: string) {
|
||||
switch (type) {
|
||||
case 'telegram_channel_request':
|
||||
case 'telegram_megagroup_request':
|
||||
case 'telegram_chat_request':
|
||||
return 'lng_view_button_request_join';
|
||||
case 'telegram_message':
|
||||
return 'lng_view_button_message';
|
||||
case 'telegram_bot':
|
||||
return 'lng_view_button_bot';
|
||||
case 'telegram_voicechat':
|
||||
return 'lng_view_button_voice_chat';
|
||||
case 'telegram_livestream':
|
||||
return 'lng_view_button_voice_chat_channel';
|
||||
case 'telegram_megagroup':
|
||||
case 'telegram_chat':
|
||||
return 'lng_view_button_group';
|
||||
case 'telegram_channel':
|
||||
return 'lng_view_button_channel';
|
||||
case 'telegram_user':
|
||||
return 'lng_view_button_user';
|
||||
case 'telegram_botapp':
|
||||
return 'lng_view_button_bot_app';
|
||||
case 'telegram_chatlist':
|
||||
return 'ViewChatList';
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@ -175,11 +175,10 @@
|
||||
}
|
||||
|
||||
&.translucent {
|
||||
--ripple-color: var(--color-interactive-element-hover);
|
||||
background-color: transparent;
|
||||
color: var(--color-text-secondary);
|
||||
|
||||
--ripple-color: var(--color-interactive-element-hover);
|
||||
|
||||
@include active-styles() {
|
||||
background-color: var(--color-interactive-element-hover);
|
||||
}
|
||||
@ -194,9 +193,9 @@
|
||||
}
|
||||
|
||||
&.translucent-white {
|
||||
--ripple-color: rgba(255, 255, 255, 0.08);
|
||||
background-color: transparent;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
--ripple-color: rgba(255, 255, 255, 0.08);
|
||||
|
||||
@include active-styles() {
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
@ -209,9 +208,9 @@
|
||||
}
|
||||
|
||||
&.translucent-black {
|
||||
--ripple-color: rgba(0, 0, 0, 0.08);
|
||||
background-color: transparent;
|
||||
color: rgba(0, 0, 0, 0.8);
|
||||
--ripple-color: rgba(0, 0, 0, 0.08);
|
||||
|
||||
@include active-styles() {
|
||||
background-color: rgba(0, 0, 0, 0.08);
|
||||
@ -222,6 +221,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.translucent-bordered {
|
||||
--ripple-color: rgba(0, 0, 0, 0.08);
|
||||
background-color: transparent;
|
||||
color: var(--accent-color);
|
||||
border: 1px solid var(--accent-color);
|
||||
|
||||
@include active-styles() {
|
||||
background-color: var(--accent-color);
|
||||
color: var(--color-white);
|
||||
}
|
||||
|
||||
@include no-ripple-styles() {
|
||||
background-color: var(--active-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.dark {
|
||||
background-color: rgba(0, 0, 0, 0.75);
|
||||
color: white;
|
||||
|
||||
@ -18,7 +18,8 @@ export type OwnProps = {
|
||||
children: React.ReactNode;
|
||||
size?: 'default' | 'smaller' | 'tiny';
|
||||
color?: (
|
||||
'primary' | 'secondary' | 'gray' | 'danger' | 'translucent' | 'translucent-white' | 'translucent-black' | 'dark'
|
||||
'primary' | 'secondary' | 'gray' | 'danger' | 'translucent' | 'translucent-white' | 'translucent-black'
|
||||
| 'translucent-bordered' | 'dark'
|
||||
);
|
||||
backgroundImage?: string;
|
||||
id?: string;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user