Composer / Web Page Preview: Add animation, fix links with _, do not show title

This commit is contained in:
Alexander Zinchuk 2021-05-06 01:47:40 +03:00
parent 987dfacaf5
commit ca65c04884
6 changed files with 64 additions and 27 deletions

View File

@ -700,9 +700,12 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
<div id="message-compose">
<div className="svg-appendix" ref={appendixRef} />
<ComposerEmbeddedMessage />
{allowedAttachmentOptions.canAttachEmbedLinks && (
<WebPagePreview chatId={chatId} threadId={threadId} messageText={!attachments.length ? html : ''} />
)}
<WebPagePreview
chatId={chatId}
threadId={threadId}
messageText={!attachments.length ? html : ''}
disabled={!allowedAttachmentOptions.canAttachEmbedLinks}
/>
<div className="message-input-wrapper">
{IS_MOBILE_SCREEN ? (
<Button

View File

@ -1,9 +1,17 @@
.WebPagePreview {
display: flex;
align-items: center;
margin-bottom: -.75rem;
padding-right: 0.625rem;
padding-top: 0.45rem;
height: 2.625rem;
transition: height 150ms ease-out, opacity 150ms ease-out;
&:not(.open) {
height: 0 !important;
}
& > div {
display: flex;
align-items: center;
padding-right: 0.625rem;
padding-top: 0.45rem;
}
--accent-color: var(--color-primary);
@ -11,7 +19,7 @@
margin-top: 0.75rem;
}
& > .Button {
& > div > .Button {
flex-shrink: 0;
background: none !important;
width: 2.125rem;
@ -26,13 +34,18 @@
margin: 0.1875rem 0 0.1875rem 0.125rem;
&::before {
top: .125rem;
bottom: .0625rem;
bottom: .125rem;
}
.site-title {
margin-top: .125rem;
margin-bottom: 0.1875rem;
}
.site-description {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
}

View File

@ -6,10 +6,14 @@ import { withGlobal } from '../../../lib/teact/teactn';
import { GlobalActions } from '../../../global/types';
import { ApiMessage, ApiMessageEntityTypes, ApiWebPage } from '../../../api/types';
import { RE_LINK_TEMPLATE } from '../../../config';
import { selectNoWebPage } from '../../../modules/selectors';
import { pick } from '../../../util/iteratees';
import parseMessageInput from './helpers/parseMessageInput';
import useOnChange from '../../../hooks/useOnChange';
import useShowTransition from '../../../hooks/useShowTransition';
import usePrevForAnimation from '../../../hooks/usePrevForAnimation';
import buildClassName from '../../../util/buildClassName';
import WebPage from '../message/WebPage';
import Button from '../../ui/Button';
@ -20,6 +24,7 @@ type OwnProps = {
chatId: number;
threadId: number;
messageText: string;
disabled?: boolean;
};
type StateProps = {
@ -28,12 +33,13 @@ type StateProps = {
};
type DispatchProps = Pick<GlobalActions, 'loadWebPagePreview' | 'clearWebPagePreview' | 'toggleMessageWebPage'>;
const RE_LINK = /https?:\/\/(www.)?([a-zA-Z0-9.-]{2,256})([a-zA-Z/.-]{1,256})([?|#][=&#a-zA-Z0-9]{2,128})?/;
const RE_LINK = new RegExp(RE_LINK_TEMPLATE, 'i');
const WebPagePreview: FC<OwnProps & StateProps & DispatchProps> = ({
chatId,
threadId,
messageText,
disabled,
webPagePreview,
noWebPage,
loadWebPagePreview,
@ -70,16 +76,21 @@ const WebPagePreview: FC<OwnProps & StateProps & DispatchProps> = ({
toggleMessageWebPage({ chatId, threadId });
}, [chatId]);
const isShown = Boolean(webPagePreview && messageText.length && !noWebPage && !disabled);
const { shouldRender, transitionClassNames } = useShowTransition(isShown);
const renderingWebPage = usePrevForAnimation(webPagePreview);
if (!shouldRender || !renderingWebPage) {
return undefined;
}
const handleClearWebpagePreview = () => {
toggleMessageWebPage({ chatId, threadId, noWebPage: true });
};
if (!webPagePreview || !messageText.length || noWebPage) {
return undefined;
}
// TODO Refactor so `WebPage` can be used without message
const { photo, ...webPageWithoutPhoto } = webPagePreview;
const { photo, ...webPageWithoutPhoto } = renderingWebPage;
const messageStub = {
content: {
webPage: webPageWithoutPhoto,
@ -87,11 +98,13 @@ const WebPagePreview: FC<OwnProps & StateProps & DispatchProps> = ({
} as ApiMessage;
return (
<div className="WebPagePreview">
<Button round color="translucent" ariaLabel="Clear Webpage Preview" onClick={handleClearWebpagePreview}>
<i className="icon-close" />
</Button>
<WebPage message={messageStub} inPreview />
<div className={buildClassName('WebPagePreview', transitionClassNames)}>
<div>
<Button round color="translucent" ariaLabel="Clear Webpage Preview" onClick={handleClearWebpagePreview}>
<i className="icon-close" />
</Button>
<WebPage message={messageStub} inPreview />
</div>
</div>
);
};

View File

@ -19,6 +19,12 @@
border-radius: 2px;
}
&-text {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.media-inner {
margin: 0 !important;
margin-bottom: 0.375rem !important;
@ -77,6 +83,7 @@
.site-name {
color: var(--accent-color);
font-weight: 500;
margin-bottom: 0.125rem;
}
.site-title {

View File

@ -1,12 +1,13 @@
import React, { FC, memo, useCallback } from '../../../lib/teact/teact';
import { ApiMessage } from '../../../api/types';
import { ObserveFn } from '../../../hooks/useIntersectionObserver';
import { getMessageWebPage } from '../../../modules/helpers';
import { calculateMediaDimensions } from './helpers/mediaDimensions';
import renderText from '../../common/helpers/renderText';
import trimText from '../../../util/trimText';
import { ObserveFn } from '../../../hooks/useIntersectionObserver';
import buildClassName from '../../../util/buildClassName';
import SafeLink from '../../common/SafeLink';
import Photo from './Photo';
@ -63,12 +64,12 @@ const WebPage: FC<OwnProps> = ({
const truncatedDescription = trimText(description, MAX_TEXT_LENGTH);
const className = [
const className = buildClassName(
'WebPage',
photo
? (isSquarePhoto && 'with-square-photo')
: (!inPreview && 'without-photo'),
].filter(Boolean).join(' ');
);
return (
<div
@ -87,7 +88,7 @@ const WebPage: FC<OwnProps> = ({
)}
<div className="WebPage-text">
<SafeLink className="site-name" url={url} text={siteName || displayUrl} />
{title && (
{!inPreview && title && (
<p className="site-title">{renderText(title)}</p>
)}
{truncatedDescription && (

View File

@ -26,5 +26,5 @@ export default function usePrevForAnimation(current: any, duration?: number) {
}
}, [current]);
return !timeoutRef.current || !duration || isCurrentPresent ? current : prev;
return isCurrentPresent || (duration && !timeoutRef.current) ? current : prev;
}