Sponsored Message: Update UI (#3989)
This commit is contained in:
parent
1ca211978c
commit
54d0ec5d7e
@ -19,6 +19,7 @@ import type {
|
|||||||
ApiReplyInfo,
|
ApiReplyInfo,
|
||||||
ApiReplyKeyboard,
|
ApiReplyKeyboard,
|
||||||
ApiSponsoredMessage,
|
ApiSponsoredMessage,
|
||||||
|
ApiSponsoredWebPage,
|
||||||
ApiSticker,
|
ApiSticker,
|
||||||
ApiStory,
|
ApiStory,
|
||||||
ApiStorySkipped,
|
ApiStorySkipped,
|
||||||
@ -77,7 +78,7 @@ export function setMessageBuilderCurrentUserId(_currentUserId: string) {
|
|||||||
export function buildApiSponsoredMessage(mtpMessage: GramJs.SponsoredMessage): ApiSponsoredMessage | undefined {
|
export function buildApiSponsoredMessage(mtpMessage: GramJs.SponsoredMessage): ApiSponsoredMessage | undefined {
|
||||||
const {
|
const {
|
||||||
fromId, message, entities, startParam, channelPost, chatInvite, chatInviteHash, randomId, recommended, sponsorInfo,
|
fromId, message, entities, startParam, channelPost, chatInvite, chatInviteHash, randomId, recommended, sponsorInfo,
|
||||||
additionalInfo,
|
additionalInfo, showPeerPhoto, webpage,
|
||||||
} = mtpMessage;
|
} = mtpMessage;
|
||||||
const chatId = fromId ? getApiChatIdFromMtpPeer(fromId) : undefined;
|
const chatId = fromId ? getApiChatIdFromMtpPeer(fromId) : undefined;
|
||||||
const chatInviteTitle = chatInvite
|
const chatInviteTitle = chatInvite
|
||||||
@ -92,6 +93,8 @@ export function buildApiSponsoredMessage(mtpMessage: GramJs.SponsoredMessage): A
|
|||||||
text: buildMessageTextContent(message, entities),
|
text: buildMessageTextContent(message, entities),
|
||||||
expiresAt: Math.round(Date.now() / 1000) + SPONSORED_MESSAGE_CACHE_MS,
|
expiresAt: Math.round(Date.now() / 1000) + SPONSORED_MESSAGE_CACHE_MS,
|
||||||
isRecommended: Boolean(recommended),
|
isRecommended: Boolean(recommended),
|
||||||
|
...(webpage && { webPage: buildSponsoredWebPage(webpage) }),
|
||||||
|
...(showPeerPhoto && { isAvatarShown: true }),
|
||||||
...(chatId && { chatId }),
|
...(chatId && { chatId }),
|
||||||
...(chatInviteHash && { chatInviteHash }),
|
...(chatInviteHash && { chatInviteHash }),
|
||||||
...(chatInvite && { chatInviteTitle }),
|
...(chatInvite && { chatInviteTitle }),
|
||||||
@ -994,3 +997,19 @@ function buildThreadInfo(
|
|||||||
...(recentRepliers && { recentReplierIds: recentRepliers.map(getApiChatIdFromMtpPeer) }),
|
...(recentRepliers && { recentReplierIds: recentRepliers.map(getApiChatIdFromMtpPeer) }),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildSponsoredWebPage(webPage: GramJs.TypeSponsoredWebPage): ApiSponsoredWebPage {
|
||||||
|
let photo: ApiPhoto | undefined;
|
||||||
|
if (webPage.photo instanceof GramJs.Photo) {
|
||||||
|
addPhotoToLocalDb(webPage.photo);
|
||||||
|
photo = buildApiPhoto(webPage.photo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...pick(webPage, [
|
||||||
|
'url',
|
||||||
|
'siteName',
|
||||||
|
]),
|
||||||
|
photo,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@ -310,6 +310,12 @@ export interface ApiWebPage {
|
|||||||
story?: ApiWebPageStoryData;
|
story?: ApiWebPageStoryData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ApiSponsoredWebPage {
|
||||||
|
url: string;
|
||||||
|
siteName: string;
|
||||||
|
photo?: ApiPhoto;
|
||||||
|
}
|
||||||
|
|
||||||
export type ApiReplyInfo = ApiMessageReplyInfo | ApiStoryReplyInfo;
|
export type ApiReplyInfo = ApiMessageReplyInfo | ApiStoryReplyInfo;
|
||||||
|
|
||||||
export interface ApiMessageReplyInfo {
|
export interface ApiMessageReplyInfo {
|
||||||
@ -571,12 +577,14 @@ export type ApiSponsoredMessage = {
|
|||||||
chatId?: string;
|
chatId?: string;
|
||||||
randomId: string;
|
randomId: string;
|
||||||
isRecommended?: boolean;
|
isRecommended?: boolean;
|
||||||
|
isAvatarShown?: boolean;
|
||||||
isBot?: boolean;
|
isBot?: boolean;
|
||||||
channelPostId?: number;
|
channelPostId?: number;
|
||||||
startParam?: string;
|
startParam?: string;
|
||||||
chatInviteHash?: string;
|
chatInviteHash?: string;
|
||||||
chatInviteTitle?: string;
|
chatInviteTitle?: string;
|
||||||
text: ApiFormattedText;
|
text: ApiFormattedText;
|
||||||
|
webPage?: ApiSponsoredWebPage;
|
||||||
expiresAt: number;
|
expiresAt: number;
|
||||||
sponsorInfo?: string;
|
sponsorInfo?: string;
|
||||||
additionalInfo?: string;
|
additionalInfo?: string;
|
||||||
|
|||||||
@ -157,6 +157,7 @@ import InlineButtons from './InlineButtons';
|
|||||||
import Invoice from './Invoice';
|
import Invoice from './Invoice';
|
||||||
import InvoiceMediaPreview from './InvoiceMediaPreview';
|
import InvoiceMediaPreview from './InvoiceMediaPreview';
|
||||||
import Location from './Location';
|
import Location from './Location';
|
||||||
|
import MessageAppendix from './MessageAppendix';
|
||||||
import MessageMeta from './MessageMeta';
|
import MessageMeta from './MessageMeta';
|
||||||
import MessagePhoneCall from './MessagePhoneCall';
|
import MessagePhoneCall from './MessagePhoneCall';
|
||||||
import Photo from './Photo';
|
import Photo from './Photo';
|
||||||
@ -1423,30 +1424,6 @@ const Message: FC<OwnProps & StateProps> = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function MessageAppendix({ isOwn } : { isOwn: boolean }) {
|
|
||||||
const path = isOwn
|
|
||||||
? 'M6 17H0V0c.193 2.84.876 5.767 2.05 8.782.904 2.325 2.446 4.485 4.625 6.48A1 1 0 016 17z'
|
|
||||||
: 'M3 17h6V0c-.193 2.84-.876 5.767-2.05 8.782-.904 2.325-2.446 4.485-4.625 6.48A1 1 0 003 17z';
|
|
||||||
return (
|
|
||||||
<svg width="9" height="20" className="svg-appendix">
|
|
||||||
<defs>
|
|
||||||
<filter x="-50%" y="-14.7%" width="200%" height="141.2%" filterUnits="objectBoundingBox" id="messageAppendix">
|
|
||||||
<feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1" />
|
|
||||||
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
|
|
||||||
<feColorMatrix
|
|
||||||
values="0 0 0 0 0.0621962482 0 0 0 0 0.138574144 0 0 0 0 0.185037364 0 0 0 0.15 0"
|
|
||||||
in="shadowBlurOuter1"
|
|
||||||
/>
|
|
||||||
</filter>
|
|
||||||
</defs>
|
|
||||||
<g fill="none" fill-rule="evenodd">
|
|
||||||
<path d={path} fill="#000" filter="url(#messageAppendix)" />
|
|
||||||
<path d={path} fill={isOwn ? '#EEFFDE' : 'FFF'} className="corner" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default memo(withGlobal<OwnProps>(
|
export default memo(withGlobal<OwnProps>(
|
||||||
(global, ownProps): StateProps => {
|
(global, ownProps): StateProps => {
|
||||||
const {
|
const {
|
||||||
|
|||||||
31
src/components/middle/message/MessageAppendix.tsx
Normal file
31
src/components/middle/message/MessageAppendix.tsx
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import React from '../../../lib/teact/teact';
|
||||||
|
|
||||||
|
interface OwnProps {
|
||||||
|
isOwn?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MessageAppendix({ isOwn } : OwnProps) {
|
||||||
|
const path = isOwn
|
||||||
|
? 'M6 17H0V0c.193 2.84.876 5.767 2.05 8.782.904 2.325 2.446 4.485 4.625 6.48A1 1 0 016 17z'
|
||||||
|
: 'M3 17h6V0c-.193 2.84-.876 5.767-2.05 8.782-.904 2.325-2.446 4.485-4.625 6.48A1 1 0 003 17z';
|
||||||
|
return (
|
||||||
|
<svg width="9" height="20" className="svg-appendix">
|
||||||
|
<defs>
|
||||||
|
<filter x="-50%" y="-14.7%" width="200%" height="141.2%" filterUnits="objectBoundingBox" id="messageAppendix">
|
||||||
|
<feOffset dy="1" in="SourceAlpha" result="shadowOffsetOuter1" />
|
||||||
|
<feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1" />
|
||||||
|
<feColorMatrix
|
||||||
|
values="0 0 0 0 0.0621962482 0 0 0 0 0.138574144 0 0 0 0 0.185037364 0 0 0 0.15 0"
|
||||||
|
in="shadowBlurOuter1"
|
||||||
|
/>
|
||||||
|
</filter>
|
||||||
|
</defs>
|
||||||
|
<g fill="none" fill-rule="evenodd">
|
||||||
|
<path d={path} fill="#000" filter="url(#messageAppendix)" />
|
||||||
|
<path d={path} fill={isOwn ? '#EEFFDE' : 'FFF'} className="corner" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MessageAppendix;
|
||||||
@ -9,10 +9,122 @@
|
|||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__button.secondary {
|
&__button {
|
||||||
margin-top: 0.5rem;
|
--riple-color: var(var(--accent-background-active-color));
|
||||||
border: 1px solid var(--color-primary);
|
|
||||||
border-radius: var(--border-radius-default-tiny);
|
margin-top: 0.375rem;
|
||||||
color: var(--color-primary);
|
margin-bottom: -0.375rem;
|
||||||
|
border-top: 1px solid var(--accent-background-active-color, var(--active-color));
|
||||||
|
|
||||||
|
color: var(--accent-color) !important;
|
||||||
|
|
||||||
|
transition: opacity 0.2s ease-in;
|
||||||
|
|
||||||
|
&:hover, &:active {
|
||||||
|
background-color: transparent !important;
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-type {
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-peer {
|
||||||
|
color: var(--color-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.with-avatar {
|
||||||
|
--border-bottom-left-radius: 0 !important;
|
||||||
|
|
||||||
|
padding-left: 2.5rem !important;
|
||||||
|
|
||||||
|
& > .Avatar {
|
||||||
|
display: flex !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
padding-left: 2.875rem !important;
|
||||||
|
|
||||||
|
.message-content {
|
||||||
|
max-width: min(29rem, calc(100vw - 7.0625rem)) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-action-button {
|
||||||
|
bottom: auto !important;
|
||||||
|
top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-content {
|
||||||
|
padding: 0.5rem;
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
max-width: min(29rem, calc(100vw - 4.5rem)) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.channel-avatar {
|
||||||
|
--radius: 0.125rem;
|
||||||
|
|
||||||
|
float: right;
|
||||||
|
margin: 0 0 0.5rem 0.5rem;
|
||||||
|
|
||||||
|
&.is-rtl {
|
||||||
|
float: left;
|
||||||
|
margin: 0 0.5rem 0.5rem 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-inner {
|
||||||
|
padding-top: 0.375rem;
|
||||||
|
padding-inline-end: 0.375rem;
|
||||||
|
padding-bottom: 0;
|
||||||
|
padding-inline-start: 0.625rem;
|
||||||
|
font-size: calc(var(--message-text-size, 1rem) - 0.125rem);
|
||||||
|
background-color: var(--accent-background-color);
|
||||||
|
border-radius: 0.375rem;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
inset-inline-start: 0;
|
||||||
|
bottom: 0;
|
||||||
|
width: 3px;
|
||||||
|
background: var(--bar-gradient, var(--accent-color));
|
||||||
|
}
|
||||||
|
|
||||||
|
> .Button {
|
||||||
|
border-radius: 0 0 0.375rem 0.375rem;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
margin-bottom: 0;
|
||||||
|
line-height: 1;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 0.0625rem;
|
||||||
|
background: var(--accent-color);
|
||||||
|
opacity: 0.25;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
top: 0.25rem;
|
||||||
|
right: 0;
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,19 +1,22 @@
|
|||||||
import type { RefObject } from 'react';
|
import type { MouseEvent as ReactMouseEvent, RefObject } from 'react';
|
||||||
import type { FC } from '../../../lib/teact/teact';
|
import type { FC } from '../../../lib/teact/teact';
|
||||||
import React, {
|
import React, { memo, useEffect, useRef } from '../../../lib/teact/teact';
|
||||||
memo, useEffect, useRef,
|
|
||||||
} from '../../../lib/teact/teact';
|
|
||||||
import { getActions, withGlobal } from '../../../global';
|
import { getActions, withGlobal } from '../../../global';
|
||||||
|
|
||||||
import type { ApiChat, ApiSponsoredMessage, ApiUser } from '../../../api/types';
|
import type {
|
||||||
|
ApiChat, ApiSponsoredMessage, ApiUser,
|
||||||
|
} from '../../../api/types';
|
||||||
|
|
||||||
import { getChatTitle, getUserFullName } from '../../../global/helpers';
|
import { getChatTitle, getUserFullName } from '../../../global/helpers';
|
||||||
import { selectChat, selectSponsoredMessage, selectUser } from '../../../global/selectors';
|
import { selectChat, selectSponsoredMessage, selectUser } from '../../../global/selectors';
|
||||||
|
import buildClassName from '../../../util/buildClassName';
|
||||||
import { IS_ANDROID, IS_TOUCH_ENV } from '../../../util/windowEnvironment';
|
import { IS_ANDROID, IS_TOUCH_ENV } from '../../../util/windowEnvironment';
|
||||||
|
import { getPeerColorClass } from '../../common/helpers/peerColor';
|
||||||
import renderText from '../../common/helpers/renderText';
|
import renderText from '../../common/helpers/renderText';
|
||||||
import { renderTextWithEntities } from '../../common/helpers/renderTextWithEntities';
|
import { renderTextWithEntities } from '../../common/helpers/renderTextWithEntities';
|
||||||
import { preventMessageInputBlur } from '../helpers/preventMessageInputBlur';
|
import { preventMessageInputBlur } from '../helpers/preventMessageInputBlur';
|
||||||
|
|
||||||
|
import useAppLayout from '../../../hooks/useAppLayout';
|
||||||
import useContextMenuHandlers from '../../../hooks/useContextMenuHandlers';
|
import useContextMenuHandlers from '../../../hooks/useContextMenuHandlers';
|
||||||
import useFlag from '../../../hooks/useFlag';
|
import useFlag from '../../../hooks/useFlag';
|
||||||
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
|
import { useIntersectionObserver } from '../../../hooks/useIntersectionObserver';
|
||||||
@ -21,7 +24,9 @@ import useLang from '../../../hooks/useLang';
|
|||||||
import useLastCallback from '../../../hooks/useLastCallback';
|
import useLastCallback from '../../../hooks/useLastCallback';
|
||||||
|
|
||||||
import AboutAdsModal from '../../common/AboutAdsModal.async';
|
import AboutAdsModal from '../../common/AboutAdsModal.async';
|
||||||
|
import Avatar from '../../common/Avatar';
|
||||||
import Button from '../../ui/Button';
|
import Button from '../../ui/Button';
|
||||||
|
import MessageAppendix from './MessageAppendix';
|
||||||
import SponsoredMessageContextMenuContainer from './SponsoredMessageContextMenuContainer.async';
|
import SponsoredMessageContextMenuContainer from './SponsoredMessageContextMenuContainer.async';
|
||||||
|
|
||||||
import './SponsoredMessage.scss';
|
import './SponsoredMessage.scss';
|
||||||
@ -33,6 +38,7 @@ type OwnProps = {
|
|||||||
|
|
||||||
type StateProps = {
|
type StateProps = {
|
||||||
message?: ApiSponsoredMessage;
|
message?: ApiSponsoredMessage;
|
||||||
|
peer?: ApiChat;
|
||||||
bot?: ApiUser;
|
bot?: ApiUser;
|
||||||
channel?: ApiChat;
|
channel?: ApiChat;
|
||||||
};
|
};
|
||||||
@ -41,6 +47,7 @@ const INTERSECTION_DEBOUNCE_MS = 200;
|
|||||||
|
|
||||||
const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
||||||
chatId,
|
chatId,
|
||||||
|
peer,
|
||||||
message,
|
message,
|
||||||
containerRef,
|
containerRef,
|
||||||
bot,
|
bot,
|
||||||
@ -52,7 +59,10 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
|||||||
openChatByInvite,
|
openChatByInvite,
|
||||||
startBot,
|
startBot,
|
||||||
focusMessage,
|
focusMessage,
|
||||||
|
openUrl,
|
||||||
|
openPremiumModal,
|
||||||
} = getActions();
|
} = getActions();
|
||||||
|
|
||||||
const lang = useLang();
|
const lang = useLang();
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
@ -72,6 +82,8 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
|||||||
handleContextMenuClose, handleContextMenuHide,
|
handleContextMenuClose, handleContextMenuHide,
|
||||||
} = useContextMenuHandlers(ref, IS_TOUCH_ENV, true, IS_ANDROID);
|
} = useContextMenuHandlers(ref, IS_TOUCH_ENV, true, IS_ANDROID);
|
||||||
const [isAboutAdsModalOpen, openAboutAdsModal, closeAboutAdsModal] = useFlag(false);
|
const [isAboutAdsModalOpen, openAboutAdsModal, closeAboutAdsModal] = useFlag(false);
|
||||||
|
const { isMobile } = useAppLayout();
|
||||||
|
const withAvatar = Boolean(message?.isAvatarShown && peer);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return shouldObserve ? observeIntersection(contentRef.current!, (target) => {
|
return shouldObserve ? observeIntersection(contentRef.current!, (target) => {
|
||||||
@ -86,6 +98,25 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
|||||||
handleBeforeContextMenu(e);
|
handleBeforeContextMenu(e);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleAvatarClick = useLastCallback(() => {
|
||||||
|
if (!peer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
openChat({ id: peer.id });
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleLinkClick = useLastCallback((e: ReactMouseEvent<HTMLButtonElement, MouseEvent>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
openUrl({ url: message!.webPage!.url, shouldSkipModal: true });
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleCloseSponsoredMessage = useLastCallback(() => {
|
||||||
|
openPremiumModal();
|
||||||
|
});
|
||||||
|
|
||||||
const handleClick = useLastCallback(() => {
|
const handleClick = useLastCallback(() => {
|
||||||
if (!message) return;
|
if (!message) return;
|
||||||
if (message.chatInviteHash) {
|
if (message.chatInviteHash) {
|
||||||
@ -108,42 +139,119 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderAvatar() {
|
||||||
|
return (
|
||||||
|
<Avatar
|
||||||
|
size={isMobile ? 'small-mobile' : 'small'}
|
||||||
|
peer={peer}
|
||||||
|
onClick={peer ? handleAvatarClick : undefined}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderContent() {
|
||||||
|
if (message?.webPage) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="text-content with-meta" dir="auto" ref={contentRef}>
|
||||||
|
<div className="message-title message-peer" dir="ltr">
|
||||||
|
{renderText(message.webPage.siteName)}
|
||||||
|
</div>
|
||||||
|
<span className="text-content-inner" dir="auto">
|
||||||
|
{renderTextWithEntities({
|
||||||
|
text: message!.text.text,
|
||||||
|
entities: message!.text.entities,
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className="SponsoredMessage__button"
|
||||||
|
size="tiny"
|
||||||
|
color="translucent"
|
||||||
|
isRectangular
|
||||||
|
onClick={handleLinkClick}
|
||||||
|
>
|
||||||
|
<i className="icon icon-arrow-right" aria-hidden />
|
||||||
|
{lang('OpenLink')}
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="message-title message-peer" dir="auto">
|
||||||
|
{bot && renderText(getUserFullName(bot) || '')}
|
||||||
|
{channel && renderText(message!.chatInviteTitle || getChatTitle(lang, channel) || '')}
|
||||||
|
</div>
|
||||||
|
<div className="text-content with-meta" dir="auto" ref={contentRef}>
|
||||||
|
<span className="text-content-inner" dir="auto">
|
||||||
|
{renderTextWithEntities({
|
||||||
|
text: message!.text.text,
|
||||||
|
entities: message!.text.entities,
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className="SponsoredMessage__button"
|
||||||
|
size="tiny"
|
||||||
|
color="translucent"
|
||||||
|
isRectangular
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
|
{lang(message!.isBot
|
||||||
|
? 'Conversation.ViewBot'
|
||||||
|
: (message!.channelPostId ? 'Conversation.ViewPost' : 'Conversation.ViewChannel'))}
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentClassName = buildClassName(
|
||||||
|
'message-content has-shadow has-solid-background',
|
||||||
|
withAvatar && 'has-appendix',
|
||||||
|
getPeerColorClass(peer || channel, true, true),
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={ref}
|
ref={ref}
|
||||||
key="sponsored-message"
|
key="sponsored-message"
|
||||||
className="SponsoredMessage Message open"
|
className={buildClassName('SponsoredMessage Message open', withAvatar && 'with-avatar')}
|
||||||
onMouseDown={handleMouseDown}
|
|
||||||
onContextMenu={handleContextMenu}
|
|
||||||
>
|
>
|
||||||
<div className="message-content has-shadow has-solid-background" dir="auto">
|
{withAvatar && renderAvatar()}
|
||||||
|
<div
|
||||||
|
className={contentClassName}
|
||||||
|
dir="auto"
|
||||||
|
onMouseDown={handleMouseDown}
|
||||||
|
onContextMenu={handleContextMenu}
|
||||||
|
>
|
||||||
<div className="content-inner" dir="auto">
|
<div className="content-inner" dir="auto">
|
||||||
<div className="message-title" dir="ltr">
|
{channel && (
|
||||||
{bot && renderText(getUserFullName(bot) || '')}
|
<Avatar
|
||||||
{channel && renderText(message.chatInviteTitle || getChatTitle(lang, channel) || '')}
|
size="large"
|
||||||
</div>
|
peer={channel}
|
||||||
|
className={buildClassName('channel-avatar', lang.isRtl && 'is-rtl')}
|
||||||
<div className="text-content with-meta" dir="auto" ref={contentRef}>
|
/>
|
||||||
<span className="text-content-inner" dir="auto">
|
)}
|
||||||
{renderTextWithEntities({
|
<span className="message-title message-type">
|
||||||
text: message.text.text,
|
{message!.isRecommended ? lang('Message.RecommendedLabel') : lang('SponsoredMessage')}
|
||||||
entities: message.text.entities,
|
</span>
|
||||||
})}
|
{renderContent()}
|
||||||
</span>
|
|
||||||
|
|
||||||
<span className="MessageMeta" dir="ltr">
|
|
||||||
<span className="message-signature">
|
|
||||||
{message.isRecommended ? lang('Message.RecommendedLabel') : lang('SponsoredMessage')}
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Button color="secondary" size="tiny" ripple onClick={handleClick} className="SponsoredMessage__button">
|
|
||||||
{lang(message.isBot
|
|
||||||
? 'Conversation.ViewBot'
|
|
||||||
: (message.channelPostId ? 'Conversation.ViewPost' : 'Conversation.ViewChannel'))}
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
|
{withAvatar && <MessageAppendix />}
|
||||||
|
<Button
|
||||||
|
className="message-action-button"
|
||||||
|
color="translucent-white"
|
||||||
|
round
|
||||||
|
size="tiny"
|
||||||
|
ariaLabel={lang('Close')}
|
||||||
|
onClick={handleCloseSponsoredMessage}
|
||||||
|
>
|
||||||
|
<i className="icon icon-close" aria-hidden />
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{contextMenuPosition && (
|
{contextMenuPosition && (
|
||||||
<SponsoredMessageContextMenuContainer
|
<SponsoredMessageContextMenuContainer
|
||||||
@ -166,10 +274,12 @@ const SponsoredMessage: FC<OwnProps & StateProps> = ({
|
|||||||
export default memo(withGlobal<OwnProps>(
|
export default memo(withGlobal<OwnProps>(
|
||||||
(global, { chatId }): StateProps => {
|
(global, { chatId }): StateProps => {
|
||||||
const message = selectSponsoredMessage(global, chatId);
|
const message = selectSponsoredMessage(global, chatId);
|
||||||
|
const peer = message?.chatId ? selectChat(global, message?.chatId) : undefined;
|
||||||
const { chatId: fromChatId, isBot } = message || {};
|
const { chatId: fromChatId, isBot } = message || {};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message,
|
message,
|
||||||
|
peer,
|
||||||
bot: fromChatId && isBot ? selectUser(global, fromChatId) : undefined,
|
bot: fromChatId && isBot ? selectUser(global, fromChatId) : undefined,
|
||||||
channel: !isBot && fromChatId ? selectChat(global, fromChatId) : undefined,
|
channel: !isBot && fromChatId ? selectChat(global, fromChatId) : undefined,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -125,7 +125,6 @@
|
|||||||
.site-description {
|
.site-description {
|
||||||
&:last-child::after {
|
&:last-child::after {
|
||||||
content: "";
|
content: "";
|
||||||
display: inline-block;
|
|
||||||
width: var(--meta-safe-area-size);
|
width: var(--meta-safe-area-size);
|
||||||
height: 0.75rem;
|
height: 0.75rem;
|
||||||
float: right;
|
float: right;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user