PLT-2321 Move the toggle icon next to the link being previewed (#3071)
* PLT-2321 Move the toggle icon next to the link being previewed only applicable to one-line messages started with link * remove useless "Youtube" header when no title is available * allow breaking long links instead of toggle * simplify "/" to "/<wbr />" replacing fix empty post without additional content body * discard buggy "simplification"
Этот коммит содержится в:
коммит произвёл
Harrison Healey
родитель
c7615920df
Коммит
e1bebb2d77
@@ -136,7 +136,6 @@ export default class PostBody extends React.Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let message;
|
let message;
|
||||||
let additionalContent = null;
|
|
||||||
if (this.props.post.state === Constants.POST_DELETED) {
|
if (this.props.post.state === Constants.POST_DELETED) {
|
||||||
message = (
|
message = (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
@@ -151,9 +150,28 @@ export default class PostBody extends React.Component {
|
|||||||
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(this.props.post.message)}}
|
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(this.props.post.message)}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
additionalContent = (
|
let messageWrapper = (
|
||||||
<PostBodyAdditionalContent post={this.props.post}/>
|
<div
|
||||||
|
key={`${post.id}_message`}
|
||||||
|
id={`${post.id}_message`}
|
||||||
|
className={postClass}
|
||||||
|
>
|
||||||
|
{loading}
|
||||||
|
{message}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
let messageWithAdditionalContent;
|
||||||
|
if (this.props.post.state === Constants.POST_DELETED) {
|
||||||
|
messageWithAdditionalContent = messageWrapper;
|
||||||
|
} else {
|
||||||
|
messageWithAdditionalContent = (
|
||||||
|
<PostBodyAdditionalContent
|
||||||
|
post={this.props.post}
|
||||||
|
message={messageWrapper}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,16 +179,8 @@ export default class PostBody extends React.Component {
|
|||||||
<div>
|
<div>
|
||||||
{comment}
|
{comment}
|
||||||
<div className='post__body'>
|
<div className='post__body'>
|
||||||
<div
|
{messageWithAdditionalContent}
|
||||||
key={`${post.id}_message`}
|
|
||||||
id={`${post.id}_message`}
|
|
||||||
className={postClass}
|
|
||||||
>
|
|
||||||
{loading}
|
|
||||||
{message}
|
|
||||||
</div>
|
|
||||||
{fileAttachmentHolder}
|
{fileAttachmentHolder}
|
||||||
{additionalContent}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -117,21 +117,31 @@ export default class PostBodyAdditionalContent extends React.Component {
|
|||||||
const generateEmbed = this.generateEmbed();
|
const generateEmbed = this.generateEmbed();
|
||||||
|
|
||||||
if (generateEmbed) {
|
if (generateEmbed) {
|
||||||
let toggle;
|
let messageWithToggle = [];
|
||||||
if (Utils.isFeatureEnabled(Constants.PRE_RELEASE_FEATURES.EMBED_TOGGLE)) {
|
if (Utils.isFeatureEnabled(Constants.PRE_RELEASE_FEATURES.EMBED_TOGGLE)) {
|
||||||
toggle = (
|
// if message has only one line and starts with a link place toggle in this only line
|
||||||
|
// else - place it in new line between message and embed
|
||||||
|
const prependToggle = (/^\s*https?:\/\/.*$/).test(this.props.post.message);
|
||||||
|
messageWithToggle.push(
|
||||||
<a
|
<a
|
||||||
className='post__embed-visibility'
|
className={`post__embed-visibility ${prependToggle ? 'pull-left' : ''}`}
|
||||||
data-expanded={this.state.embedVisible}
|
data-expanded={this.state.embedVisible}
|
||||||
aria-label='Toggle Embed Visibility'
|
aria-label='Toggle Embed Visibility'
|
||||||
onClick={this.toggleEmbedVisibility}
|
onClick={this.toggleEmbedVisibility}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
if (prependToggle) {
|
||||||
|
messageWithToggle.push(this.props.message);
|
||||||
|
} else {
|
||||||
|
messageWithToggle.unshift(this.props.message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
messageWithToggle.push(this.props.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{toggle}
|
{messageWithToggle}
|
||||||
<div
|
<div
|
||||||
className='post__embed-container'
|
className='post__embed-container'
|
||||||
hidden={!this.state.embedVisible}
|
hidden={!this.state.embedVisible}
|
||||||
@@ -142,10 +152,11 @@ export default class PostBodyAdditionalContent extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return this.props.message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PostBodyAdditionalContent.propTypes = {
|
PostBodyAdditionalContent.propTypes = {
|
||||||
post: React.PropTypes.object.isRequired
|
post: React.PropTypes.object.isRequired,
|
||||||
|
message: React.PropTypes.element.isRequired
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -210,6 +210,14 @@ export default class RhsRootPost extends React.Component {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const messageWrapper = (
|
||||||
|
<div
|
||||||
|
ref='message_holder'
|
||||||
|
onClick={TextFormatting.handleClick}
|
||||||
|
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(post.message)}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'post post--root ' + userCss + ' ' + systemMessageClass}>
|
<div className={'post post--root ' + userCss + ' ' + systemMessageClass}>
|
||||||
<div className='post-right-channel__name'>{channelName}</div>
|
<div className='post-right-channel__name'>{channelName}</div>
|
||||||
@@ -241,13 +249,9 @@ export default class RhsRootPost extends React.Component {
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div className='post__body'>
|
<div className='post__body'>
|
||||||
<div
|
|
||||||
ref='message_holder'
|
|
||||||
onClick={TextFormatting.handleClick}
|
|
||||||
dangerouslySetInnerHTML={{__html: TextFormatting.formatText(post.message)}}
|
|
||||||
/>
|
|
||||||
<PostBodyAdditionalContent
|
<PostBodyAdditionalContent
|
||||||
post={post}
|
post={post}
|
||||||
|
message={messageWrapper}
|
||||||
/>
|
/>
|
||||||
{fileAttachment}
|
{fileAttachment}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -144,9 +144,22 @@ export default class YoutubeVideo extends React.Component {
|
|||||||
return <div className='video-loading'/>;
|
return <div className='video-loading'/>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let header = 'Youtube';
|
let header;
|
||||||
if (this.state.title) {
|
if (this.state.title) {
|
||||||
header = header + ' - ';
|
header = (
|
||||||
|
<h4>
|
||||||
|
<span className='video-type'>{'Youtube - '}</span>
|
||||||
|
<span className='video-title'>
|
||||||
|
<a
|
||||||
|
href={this.props.link}
|
||||||
|
target='blank'
|
||||||
|
rel='noopener noreferrer'
|
||||||
|
>
|
||||||
|
{this.state.title}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</h4>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let content;
|
let content;
|
||||||
@@ -190,18 +203,7 @@ export default class YoutubeVideo extends React.Component {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h4>
|
{header}
|
||||||
<span className='video-type'>{header}</span>
|
|
||||||
<span className='video-title'>
|
|
||||||
<a
|
|
||||||
href={this.props.link}
|
|
||||||
target='blank'
|
|
||||||
rel='noopener noreferrer'
|
|
||||||
>
|
|
||||||
{this.state.title}
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</h4>
|
|
||||||
<div
|
<div
|
||||||
className='video-div embed-responsive-item'
|
className='video-div embed-responsive-item'
|
||||||
onClick={this.play}
|
onClick={this.play}
|
||||||
|
|||||||
@@ -914,9 +914,13 @@ body.ios {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font: normal normal normal 14px/1 FontAwesome;
|
font: normal normal normal 14px/1 FontAwesome;
|
||||||
margin: 5px 0 10px;
|
margin: 0 0 10px;
|
||||||
text-rendering: auto;
|
text-rendering: auto;
|
||||||
|
|
||||||
|
&.pull-left{
|
||||||
|
margin: 5px 5px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ export function formatText(text, options = {}) {
|
|||||||
output = replaceNewlines(output);
|
output = replaceNewlines(output);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output = insertLongLinkWbr(output);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +78,9 @@ export function doFormatText(text, options) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//replace all "/" to "/<wbr />"
|
||||||
|
output = output.replace(/\//g, '/<wbr />');
|
||||||
|
|
||||||
// reinsert tokens with formatted versions of the important words and phrases
|
// reinsert tokens with formatted versions of the important words and phrases
|
||||||
output = replaceTokens(output, tokens);
|
output = replaceTokens(output, tokens);
|
||||||
|
|
||||||
@@ -425,3 +430,10 @@ export function handleClick(e) {
|
|||||||
browserHistory.push(linkAttribute.value);
|
browserHistory.push(linkAttribute.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//replace all "/" inside <a> tags to "/<wbr />"
|
||||||
|
function insertLongLinkWbr(test) {
|
||||||
|
return test.replace(/\//g, (match, position, string) => {
|
||||||
|
return match + ((/a[^>]*>[^<]*$/).test(string.substr(0, position)) ? '<wbr />' : '');
|
||||||
|
});
|
||||||
|
}
|
||||||
Ссылка в новой задаче
Block a user