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 {
|
function buildReplyButtons(message: UniversalMessage, shouldSkipBuyButton?: boolean): ApiReplyKeyboard | undefined {
|
||||||
const { replyMarkup, media } = message;
|
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)) {
|
if (!(replyMarkup instanceof GramJs.ReplyKeyboardMarkup || replyMarkup instanceof GramJs.ReplyInlineMarkup)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,22 +1,33 @@
|
|||||||
.WebPage {
|
.WebPage {
|
||||||
margin-top: 0.25rem;
|
margin-top: 0.25rem;
|
||||||
margin-bottom: 0.125rem;
|
margin-bottom: 0.125rem;
|
||||||
padding-left: 0.625rem;
|
|
||||||
font-size: calc(var(--message-text-size, 1rem) - 0.125rem);
|
font-size: calc(var(--message-text-size, 1rem) - 0.125rem);
|
||||||
line-height: 1.125rem;
|
line-height: 1.125rem;
|
||||||
max-width: 29rem;
|
max-width: 29rem;
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&::before {
|
.WebPage--content {
|
||||||
content: "";
|
padding-left: 0.625rem;
|
||||||
display: block;
|
position: relative;
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
&::before {
|
||||||
bottom: 0;
|
content: "";
|
||||||
left: 0;
|
display: block;
|
||||||
width: 0.125rem;
|
position: absolute;
|
||||||
background: var(--accent-color);
|
top: 0;
|
||||||
border-radius: 0.125rem;
|
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 {
|
&-text {
|
||||||
@ -55,13 +66,14 @@
|
|||||||
margin-bottom: 1rem !important;
|
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;
|
margin-bottom: 1rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.with-square-photo {
|
&.with-square-photo .WebPage--content {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-bottom: 1rem;
|
|
||||||
|
|
||||||
.WebPage-text {
|
.WebPage-text {
|
||||||
order: 1;
|
order: 1;
|
||||||
@ -92,7 +104,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.with-square-photo) {
|
&:not(.with-square-photo):not(.with-quick-button) {
|
||||||
.site-name,
|
.site-name,
|
||||||
.site-title,
|
.site-title,
|
||||||
.site-description {
|
.site-description {
|
||||||
|
|||||||
@ -1,20 +1,25 @@
|
|||||||
import type { FC } from '../../../lib/teact/teact';
|
|
||||||
import React, { memo, useCallback } 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 { ApiMessage } from '../../../api/types';
|
||||||
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
import type { ObserveFn } from '../../../hooks/useIntersectionObserver';
|
||||||
import type { ISettings } from '../../../types';
|
import type { ISettings } from '../../../types';
|
||||||
|
|
||||||
import { getMessageWebPage } from '../../../global/helpers';
|
import { getMessageWebPage } from '../../../global/helpers';
|
||||||
import { calculateMediaDimensions } from './helpers/mediaDimensions';
|
import { calculateMediaDimensions } from './helpers/mediaDimensions';
|
||||||
|
import { getWebpageButtonText } from './helpers/webpageType';
|
||||||
import renderText from '../../common/helpers/renderText';
|
import renderText from '../../common/helpers/renderText';
|
||||||
import trimText from '../../../util/trimText';
|
import trimText from '../../../util/trimText';
|
||||||
import buildClassName from '../../../util/buildClassName';
|
import buildClassName from '../../../util/buildClassName';
|
||||||
|
|
||||||
import useAppLayout from '../../../hooks/useAppLayout';
|
import useAppLayout from '../../../hooks/useAppLayout';
|
||||||
|
import useLang from '../../../hooks/useLang';
|
||||||
|
|
||||||
import SafeLink from '../../common/SafeLink';
|
import SafeLink from '../../common/SafeLink';
|
||||||
import Photo from './Photo';
|
import Photo from './Photo';
|
||||||
import Video from './Video';
|
import Video from './Video';
|
||||||
|
import Button from '../../ui/Button';
|
||||||
|
|
||||||
import './WebPage.scss';
|
import './WebPage.scss';
|
||||||
|
|
||||||
@ -51,13 +56,23 @@ const WebPage: FC<OwnProps> = ({
|
|||||||
onMediaClick,
|
onMediaClick,
|
||||||
onCancelMediaTransfer,
|
onCancelMediaTransfer,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { openTelegramLink } = getActions();
|
||||||
const webPage = getMessageWebPage(message);
|
const webPage = getMessageWebPage(message);
|
||||||
const { isMobile } = useAppLayout();
|
const { isMobile } = useAppLayout();
|
||||||
|
|
||||||
|
const lang = useLang();
|
||||||
|
|
||||||
const handleMediaClick = useCallback(() => {
|
const handleMediaClick = useCallback(() => {
|
||||||
onMediaClick!();
|
onMediaClick!();
|
||||||
}, [onMediaClick]);
|
}, [onMediaClick]);
|
||||||
|
|
||||||
|
const handleQuickButtonClick = useCallback(() => {
|
||||||
|
if (!webPage) return;
|
||||||
|
openTelegramLink({
|
||||||
|
url: webPage.url,
|
||||||
|
});
|
||||||
|
}, [webPage]);
|
||||||
|
|
||||||
if (!webPage) {
|
if (!webPage) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -70,7 +85,9 @@ const WebPage: FC<OwnProps> = ({
|
|||||||
description,
|
description,
|
||||||
photo,
|
photo,
|
||||||
video,
|
video,
|
||||||
|
type,
|
||||||
} = webPage;
|
} = webPage;
|
||||||
|
const quickButtonLangKey = !inPreview ? getWebpageButtonText(type) : undefined;
|
||||||
const truncatedDescription = trimText(description, MAX_TEXT_LENGTH);
|
const truncatedDescription = trimText(description, MAX_TEXT_LENGTH);
|
||||||
const isArticle = Boolean(truncatedDescription || title || siteName);
|
const isArticle = Boolean(truncatedDescription || title || siteName);
|
||||||
let isSquarePhoto = false;
|
let isSquarePhoto = false;
|
||||||
@ -87,56 +104,73 @@ const WebPage: FC<OwnProps> = ({
|
|||||||
!photo && !video && !inPreview && 'without-media',
|
!photo && !video && !inPreview && 'without-media',
|
||||||
video && 'with-video',
|
video && 'with-video',
|
||||||
!isArticle && 'no-article',
|
!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 (
|
return (
|
||||||
<div
|
<div
|
||||||
className={className}
|
className={className}
|
||||||
data-initial={(siteName || displayUrl)[0]}
|
data-initial={(siteName || displayUrl)[0]}
|
||||||
dir="auto"
|
dir="auto"
|
||||||
>
|
>
|
||||||
{photo && !video && (
|
<div className="WebPage--content">
|
||||||
<Photo
|
{photo && !video && (
|
||||||
message={message}
|
<Photo
|
||||||
observeIntersection={observeIntersection}
|
message={message}
|
||||||
noAvatars={noAvatars}
|
observeIntersection={observeIntersection}
|
||||||
canAutoLoad={canAutoLoad}
|
noAvatars={noAvatars}
|
||||||
size={isSquarePhoto ? 'pictogram' : 'inline'}
|
canAutoLoad={canAutoLoad}
|
||||||
asForwarded={asForwarded}
|
size={isSquarePhoto ? 'pictogram' : 'inline'}
|
||||||
nonInteractive={!isMediaInteractive}
|
asForwarded={asForwarded}
|
||||||
isDownloading={isDownloading}
|
nonInteractive={!isMediaInteractive}
|
||||||
isProtected={isProtected}
|
isDownloading={isDownloading}
|
||||||
theme={theme}
|
isProtected={isProtected}
|
||||||
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
theme={theme}
|
||||||
onCancelUpload={onCancelMediaTransfer}
|
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
||||||
/>
|
onCancelUpload={onCancelMediaTransfer}
|
||||||
)}
|
/>
|
||||||
{isArticle && (
|
)}
|
||||||
<div className="WebPage-text">
|
{isArticle && (
|
||||||
<SafeLink className="site-name" url={url} text={siteName || displayUrl} />
|
<div className="WebPage-text">
|
||||||
{!inPreview && title && (
|
<SafeLink className="site-name" url={url} text={siteName || displayUrl} />
|
||||||
<p className="site-title">{renderText(title)}</p>
|
{!inPreview && title && (
|
||||||
)}
|
<p className="site-title">{renderText(title)}</p>
|
||||||
{truncatedDescription && (
|
)}
|
||||||
<p className="site-description">{renderText(truncatedDescription, ['emoji', 'br'])}</p>
|
{truncatedDescription && (
|
||||||
)}
|
<p className="site-description">{renderText(truncatedDescription, ['emoji', 'br'])}</p>
|
||||||
</div>
|
)}
|
||||||
)}
|
</div>
|
||||||
{!inPreview && video && (
|
)}
|
||||||
<Video
|
{!inPreview && video && (
|
||||||
message={message}
|
<Video
|
||||||
observeIntersectionForLoading={observeIntersection!}
|
message={message}
|
||||||
noAvatars={noAvatars}
|
observeIntersectionForLoading={observeIntersection!}
|
||||||
canAutoLoad={canAutoLoad}
|
noAvatars={noAvatars}
|
||||||
canAutoPlay={canAutoPlay}
|
canAutoLoad={canAutoLoad}
|
||||||
lastSyncTime={lastSyncTime}
|
canAutoPlay={canAutoPlay}
|
||||||
asForwarded={asForwarded}
|
lastSyncTime={lastSyncTime}
|
||||||
isDownloading={isDownloading}
|
asForwarded={asForwarded}
|
||||||
isProtected={isProtected}
|
isDownloading={isDownloading}
|
||||||
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
isProtected={isProtected}
|
||||||
onCancelUpload={onCancelMediaTransfer}
|
onClick={isMediaInteractive ? handleMediaClick : undefined}
|
||||||
/>
|
onCancelUpload={onCancelMediaTransfer}
|
||||||
)}
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{quickButtonLangKey && renderQuickButton(quickButtonLangKey)}
|
||||||
</div>
|
</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 {
|
&.translucent {
|
||||||
|
--ripple-color: var(--color-interactive-element-hover);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: var(--color-text-secondary);
|
color: var(--color-text-secondary);
|
||||||
|
|
||||||
--ripple-color: var(--color-interactive-element-hover);
|
|
||||||
|
|
||||||
@include active-styles() {
|
@include active-styles() {
|
||||||
background-color: var(--color-interactive-element-hover);
|
background-color: var(--color-interactive-element-hover);
|
||||||
}
|
}
|
||||||
@ -194,9 +193,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.translucent-white {
|
&.translucent-white {
|
||||||
|
--ripple-color: rgba(255, 255, 255, 0.08);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: rgba(255, 255, 255, 0.5);
|
color: rgba(255, 255, 255, 0.5);
|
||||||
--ripple-color: rgba(255, 255, 255, 0.08);
|
|
||||||
|
|
||||||
@include active-styles() {
|
@include active-styles() {
|
||||||
background-color: rgba(255, 255, 255, 0.08);
|
background-color: rgba(255, 255, 255, 0.08);
|
||||||
@ -209,9 +208,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.translucent-black {
|
&.translucent-black {
|
||||||
|
--ripple-color: rgba(0, 0, 0, 0.08);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: rgba(0, 0, 0, 0.8);
|
color: rgba(0, 0, 0, 0.8);
|
||||||
--ripple-color: rgba(0, 0, 0, 0.08);
|
|
||||||
|
|
||||||
@include active-styles() {
|
@include active-styles() {
|
||||||
background-color: rgba(0, 0, 0, 0.08);
|
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 {
|
&.dark {
|
||||||
background-color: rgba(0, 0, 0, 0.75);
|
background-color: rgba(0, 0, 0, 0.75);
|
||||||
color: white;
|
color: white;
|
||||||
|
|||||||
@ -18,7 +18,8 @@ export type OwnProps = {
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
size?: 'default' | 'smaller' | 'tiny';
|
size?: 'default' | 'smaller' | 'tiny';
|
||||||
color?: (
|
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;
|
backgroundImage?: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user