Merge branch 'master' into patch-2
This commit is contained in:
@ -1,9 +1,35 @@
|
||||
import emojione from 'emojione';
|
||||
|
||||
emojione.imageType = 'png';
|
||||
emojione.sprites = false;
|
||||
emojione.imagePathPNG = '/emoji/';
|
||||
const toImage = str => shortnameToImage(unicodeToImage(str));
|
||||
|
||||
const unicodeToImage = str => {
|
||||
const mappedUnicode = emojione.mapUnicodeToShort();
|
||||
|
||||
return str.replace(emojione.regUnicode, unicodeChar => {
|
||||
if (typeof unicodeChar === 'undefined' || unicodeChar === '' || !(unicodeChar in emojione.jsEscapeMap)) {
|
||||
return unicodeChar;
|
||||
}
|
||||
|
||||
const unicode = emojione.jsEscapeMap[unicodeChar];
|
||||
const short = mappedUnicode[unicode];
|
||||
const filename = emojione.emojioneList[short].fname;
|
||||
const alt = emojione.convert(unicode.toUpperCase());
|
||||
|
||||
return `<img draggable="false" class="emojione" alt="${alt}" src="/emoji/${filename}.svg" />`;
|
||||
});
|
||||
};
|
||||
|
||||
const shortnameToImage = str => str.replace(emojione.regShortNames, shortname => {
|
||||
if (typeof shortname === 'undefined' || shortname === '' || !(shortname in emojione.emojioneList)) {
|
||||
return shortname;
|
||||
}
|
||||
|
||||
const unicode = emojione.emojioneList[shortname].unicode[emojione.emojioneList[shortname].unicode.length - 1];
|
||||
const alt = emojione.convert(unicode.toUpperCase());
|
||||
|
||||
return `<img draggable="false" class="emojione" alt="${alt}" src="/emoji/${unicode}.svg" />`;
|
||||
});
|
||||
|
||||
export default function emojify(text) {
|
||||
return emojione.toImage(text);
|
||||
return toImage(text);
|
||||
};
|
||||
|
@ -4,6 +4,7 @@ import emojify from '../../../emoji';
|
||||
import escapeTextContentForBrowser from 'escape-html';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
import IconButton from '../../../components/icon_button';
|
||||
import { Motion, spring } from 'react-motion';
|
||||
|
||||
const messages = defineMessages({
|
||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||
@ -11,6 +12,47 @@ const messages = defineMessages({
|
||||
requested: { id: 'account.requested', defaultMessage: 'Awaiting approval' }
|
||||
});
|
||||
|
||||
const Avatar = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
account: ImmutablePropTypes.map.isRequired
|
||||
},
|
||||
|
||||
getInitialState () {
|
||||
return {
|
||||
isHovered: false
|
||||
};
|
||||
},
|
||||
|
||||
mixins: [PureRenderMixin],
|
||||
|
||||
handleMouseOver () {
|
||||
if (this.state.isHovered) return;
|
||||
this.setState({ isHovered: true });
|
||||
},
|
||||
|
||||
handleMouseOut () {
|
||||
if (!this.state.isHovered) return;
|
||||
this.setState({ isHovered: false });
|
||||
},
|
||||
|
||||
render () {
|
||||
const { account } = this.props;
|
||||
const { isHovered } = this.state;
|
||||
|
||||
return (
|
||||
<Motion defaultStyle={{ radius: 90 }} style={{ radius: spring(isHovered ? 30 : 90, { stiffness: 180, damping: 12 }) }}>
|
||||
{({ radius }) =>
|
||||
<a href={account.get('url')} className='account__header__avatar' target='_blank' rel='noopener' style={{ display: 'block', width: '90px', height: '90px', margin: '0 auto', marginBottom: '10px', borderRadius: `${radius}px`, overflow: 'hidden' }} onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut}>
|
||||
<img src={account.get('avatar')} alt={account.get('acct')} style={{ display: 'block', width: '90px', height: '90px' }} />
|
||||
</a>
|
||||
}
|
||||
</Motion>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
const Header = React.createClass({
|
||||
|
||||
propTypes: {
|
||||
@ -68,14 +110,9 @@ const Header = React.createClass({
|
||||
return (
|
||||
<div className='account__header' style={{ backgroundImage: `url(${account.get('header')})` }}>
|
||||
<div style={{ padding: '20px 10px' }}>
|
||||
<a href={account.get('url')} target='_blank' rel='noopener' style={{ display: 'block', color: 'inherit', textDecoration: 'none' }}>
|
||||
<div className='account__header__avatar' style={{ width: '90px', margin: '0 auto', marginBottom: '10px' }}>
|
||||
<img src={account.get('avatar')} alt='' style={{ display: 'block', width: '90px', height: '90px', borderRadius: '90px' }} />
|
||||
</div>
|
||||
|
||||
<span style={{ display: 'inline-block', fontSize: '20px', lineHeight: '27px', fontWeight: '500' }} className='account__header__display-name' dangerouslySetInnerHTML={displayNameHTML} />
|
||||
</a>
|
||||
<Avatar account={account} />
|
||||
|
||||
<span style={{ display: 'inline-block', fontSize: '20px', lineHeight: '27px', fontWeight: '500' }} className='account__header__display-name' dangerouslySetInnerHTML={displayNameHTML} />
|
||||
<span className='account__header__username' style={{ fontSize: '14px', fontWeight: '400', display: 'block', marginBottom: '10px' }}>@{account.get('acct')} {lockedIcon}</span>
|
||||
<div style={{ fontSize: '14px' }} className='account__header__content' dangerouslySetInnerHTML={content} />
|
||||
|
||||
|
@ -43,7 +43,7 @@ const EmojiPickerDropdown = React.createClass({
|
||||
return (
|
||||
<Dropdown ref={this.setRef} style={style}>
|
||||
<DropdownTrigger className='emoji-button' title={intl.formatMessage(messages.emoji)} style={{ fontSize: `24px`, width: `24px`, lineHeight: `24px`, display: 'block', marginLeft: '2px' }}>
|
||||
<img className="emojione" alt="🙂" src="/emoji/1f602.png" />
|
||||
<img draggable="false" className="emojione" alt="🙂" src="/emoji/1f602.svg" />
|
||||
</DropdownTrigger>
|
||||
|
||||
<DropdownContent className='dropdown__left'>
|
||||
|
@ -41,7 +41,7 @@ const GettingStarted = ({ intl, me }) => {
|
||||
<ColumnLink icon='sign-out' text={intl.formatMessage(messages.sign_out)} href='/auth/sign_out' method='delete' />
|
||||
</div>
|
||||
|
||||
<div className='scrollable optionally-scrollable'>
|
||||
<div className='scrollable optionally-scrollable' style={{ display: 'flex', flexDirection: 'column' }}>
|
||||
<div className='static-content getting-started'>
|
||||
<p><FormattedMessage id='getting_started.about_addressing' defaultMessage='You can follow people if you know their username and the domain they are on by entering an e-mail-esque address into the form at the top of the sidebar.' /></p>
|
||||
<p><FormattedMessage id='getting_started.about_shortcuts' defaultMessage='If the target user is on the same domain as you, just the username will work. The same rule applies to mentioning people in statuses.' /></p>
|
||||
|
@ -36,34 +36,62 @@ const UI = React.createClass({
|
||||
this.setState({ width: window.innerWidth });
|
||||
},
|
||||
|
||||
handleDragEnter (e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (!this.dragTargets) {
|
||||
this.dragTargets = [];
|
||||
}
|
||||
|
||||
if (this.dragTargets.indexOf(e.target) === -1) {
|
||||
this.dragTargets.push(e.target);
|
||||
}
|
||||
|
||||
this.setState({ draggingOver: true });
|
||||
},
|
||||
|
||||
handleDragOver (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
e.dataTransfer.dropEffect = 'copy';
|
||||
try {
|
||||
e.dataTransfer.dropEffect = 'copy';
|
||||
} catch (err) {
|
||||
|
||||
if (e.dataTransfer.effectAllowed === 'all' || e.dataTransfer.effectAllowed === 'uninitialized') {
|
||||
this.setState({ draggingOver: true });
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
handleDrop (e) {
|
||||
e.preventDefault();
|
||||
|
||||
this.setState({ draggingOver: false });
|
||||
|
||||
if (e.dataTransfer && e.dataTransfer.files.length === 1) {
|
||||
this.setState({ draggingOver: false });
|
||||
this.props.dispatch(uploadCompose(e.dataTransfer.files));
|
||||
}
|
||||
},
|
||||
|
||||
handleDragLeave () {
|
||||
handleDragLeave (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.dragTargets = this.dragTargets.filter(el => el !== e.target && this.node.contains(el));
|
||||
|
||||
if (this.dragTargets.length > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setState({ draggingOver: false });
|
||||
},
|
||||
|
||||
componentWillMount () {
|
||||
window.addEventListener('resize', this.handleResize, { passive: true });
|
||||
window.addEventListener('dragover', this.handleDragOver);
|
||||
window.addEventListener('drop', this.handleDrop);
|
||||
document.addEventListener('dragenter', this.handleDragEnter, false);
|
||||
document.addEventListener('dragover', this.handleDragOver, false);
|
||||
document.addEventListener('drop', this.handleDrop, false);
|
||||
document.addEventListener('dragleave', this.handleDragLeave, false);
|
||||
|
||||
this.props.dispatch(refreshTimeline('home'));
|
||||
this.props.dispatch(refreshNotifications());
|
||||
@ -71,8 +99,14 @@ const UI = React.createClass({
|
||||
|
||||
componentWillUnmount () {
|
||||
window.removeEventListener('resize', this.handleResize);
|
||||
window.removeEventListener('dragover', this.handleDragOver);
|
||||
window.removeEventListener('drop', this.handleDrop);
|
||||
document.removeEventListener('dragenter', this.handleDragEnter);
|
||||
document.removeEventListener('dragover', this.handleDragOver);
|
||||
document.removeEventListener('drop', this.handleDrop);
|
||||
document.removeEventListener('dragleave', this.handleDragLeave);
|
||||
},
|
||||
|
||||
setRef (c) {
|
||||
this.node = c;
|
||||
},
|
||||
|
||||
render () {
|
||||
@ -99,7 +133,7 @@ const UI = React.createClass({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='ui' onDragLeave={this.handleDragLeave}>
|
||||
<div className='ui' ref={this.setRef}>
|
||||
<TabsBar />
|
||||
|
||||
{mountedColumns}
|
||||
|
Reference in New Issue
Block a user