Progress
This commit is contained in:
parent
fa66d082f8
commit
1c98dd283e
|
@ -3,7 +3,6 @@
|
||||||
import Rails from 'rails-ujs';
|
import Rails from 'rails-ujs';
|
||||||
|
|
||||||
export function start() {
|
export function start() {
|
||||||
require('font-awesome/css/font-awesome.css');
|
|
||||||
require.context('../images/', true);
|
require.context('../images/', true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import { Fragment } from 'react';
|
import { Fragment } from 'react'
|
||||||
import { Link } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { me } from '../../initial_state';
|
import { me } from '../../initial_state'
|
||||||
import Avatar from '../avatar/avatar';
|
import Avatar from '../avatar/avatar'
|
||||||
import DisplayName from '../display_name';
|
import DisplayName from '../display_name'
|
||||||
import IconButton from '../icon_button';
|
import IconButton from '../icon_button'
|
||||||
|
import Icon from '../icon'
|
||||||
import './account.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||||
|
@ -18,7 +17,7 @@ const messages = defineMessages({
|
||||||
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
|
unmute: { id: 'account.unmute', defaultMessage: 'Unmute @{name}' },
|
||||||
mute_notifications: { id: 'account.mute_notifications', defaultMessage: 'Mute notifications from @{name}' },
|
mute_notifications: { id: 'account.mute_notifications', defaultMessage: 'Mute notifications from @{name}' },
|
||||||
unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'Unmute notifications from @{name}' },
|
unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'Unmute notifications from @{name}' },
|
||||||
});
|
})
|
||||||
|
|
||||||
export default @injectIntl
|
export default @injectIntl
|
||||||
class Account extends ImmutablePureComponent {
|
class Account extends ImmutablePureComponent {
|
||||||
|
@ -34,37 +33,36 @@ class Account extends ImmutablePureComponent {
|
||||||
actionIcon: PropTypes.string,
|
actionIcon: PropTypes.string,
|
||||||
actionTitle: PropTypes.string,
|
actionTitle: PropTypes.string,
|
||||||
onActionClick: PropTypes.func,
|
onActionClick: PropTypes.func,
|
||||||
displayOnly: PropTypes.bool,
|
}
|
||||||
};
|
|
||||||
|
|
||||||
handleFollow = () => {
|
handleFollow = () => {
|
||||||
this.props.onFollow(this.props.account);
|
this.props.onFollow(this.props.account)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleBlock = () => {
|
handleBlock = () => {
|
||||||
this.props.onBlock(this.props.account);
|
this.props.onBlock(this.props.account)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMute = () => {
|
handleMute = () => {
|
||||||
this.props.onMute(this.props.account);
|
this.props.onMute(this.props.account)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMuteNotifications = () => {
|
handleMuteNotifications = () => {
|
||||||
this.props.onMuteNotifications(this.props.account, true);
|
this.props.onMuteNotifications(this.props.account, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleUnmuteNotifications = () => {
|
handleUnmuteNotifications = () => {
|
||||||
this.props.onMuteNotifications(this.props.account, false);
|
this.props.onMuteNotifications(this.props.account, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAction = () => {
|
handleAction = () => {
|
||||||
this.props.onActionClick(this.props.account);
|
this.props.onActionClick(this.props.account)
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { account, intl, hidden, onActionClick, actionIcon, actionTitle, displayOnly } = this.props;
|
const { account, intl, hidden, onActionClick, actionIcon, actionTitle } = this.props
|
||||||
|
|
||||||
if (!account) return null;
|
if (!account) return null
|
||||||
|
|
||||||
if (hidden) {
|
if (hidden) {
|
||||||
return (
|
return (
|
||||||
|
@ -72,29 +70,29 @@ class Account extends ImmutablePureComponent {
|
||||||
{account.get('display_name')}
|
{account.get('display_name')}
|
||||||
{account.get('username')}
|
{account.get('username')}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
let buttons;
|
let buttons
|
||||||
|
|
||||||
if (onActionClick && actionIcon) {
|
if (onActionClick && actionIcon) {
|
||||||
buttons = <IconButton icon={actionIcon} title={actionTitle} onClick={this.handleAction} />;
|
buttons = <IconButton icon={actionIcon} title={actionTitle} onClick={this.handleAction} />
|
||||||
} else if (account.get('id') !== me && account.get('relationship', null) !== null) {
|
} else if (account.get('id') !== me && account.get('relationship', null) !== null) {
|
||||||
const following = account.getIn(['relationship', 'following']);
|
const following = account.getIn(['relationship', 'following'])
|
||||||
const requested = account.getIn(['relationship', 'requested']);
|
const requested = account.getIn(['relationship', 'requested'])
|
||||||
const blocking = account.getIn(['relationship', 'blocking']);
|
const blocking = account.getIn(['relationship', 'blocking'])
|
||||||
const muting = account.getIn(['relationship', 'muting']);
|
const muting = account.getIn(['relationship', 'muting'])
|
||||||
|
|
||||||
if (requested) {
|
if (requested) {
|
||||||
buttons = <IconButton disabled icon='hourglass' title={intl.formatMessage(messages.requested)} />;
|
buttons = <IconButton disabled icon='hourglass' title={intl.formatMessage(messages.requested)} />
|
||||||
} else if (blocking) {
|
} else if (blocking) {
|
||||||
buttons = <IconButton active icon='unlock' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.handleBlock} />;
|
buttons = <IconButton active icon='unlock' title={intl.formatMessage(messages.unblock, { name: account.get('username') })} onClick={this.handleBlock} />
|
||||||
} else if (muting) {
|
} else if (muting) {
|
||||||
let hidingNotificationsButton;
|
let hidingNotificationsButton
|
||||||
if (account.getIn(['relationship', 'muting_notifications'])) {
|
if (account.getIn(['relationship', 'muting_notifications'])) {
|
||||||
hidingNotificationsButton = <IconButton active icon='bell' title={intl.formatMessage(messages.unmute_notifications, { name: account.get('username') })} onClick={this.handleUnmuteNotifications} />;
|
hidingNotificationsButton = <IconButton active icon='bell' title={intl.formatMessage(messages.unmute_notifications, { name: account.get('username') })} onClick={this.handleUnmuteNotifications} />
|
||||||
} else {
|
} else {
|
||||||
hidingNotificationsButton = <IconButton active icon='bell-slash' title={intl.formatMessage(messages.mute_notifications, { name: account.get('username') })} onClick={this.handleMuteNotifications} />;
|
hidingNotificationsButton = <IconButton active icon='bell-slash' title={intl.formatMessage(messages.mute_notifications, { name: account.get('username') })} onClick={this.handleMuteNotifications} />
|
||||||
}
|
}
|
||||||
|
|
||||||
buttons = (
|
buttons = (
|
||||||
|
@ -102,41 +100,44 @@ class Account extends ImmutablePureComponent {
|
||||||
<IconButton active icon='volume-up' title={intl.formatMessage(messages.unmute, { name: account.get('username') })} onClick={this.handleMute} />
|
<IconButton active icon='volume-up' title={intl.formatMessage(messages.unmute, { name: account.get('username') })} onClick={this.handleMute} />
|
||||||
{hidingNotificationsButton}
|
{hidingNotificationsButton}
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
)
|
||||||
} else if (!account.get('moved') || following) {
|
} else if (!account.get('moved') || following) {
|
||||||
buttons = <IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} active={following} />;
|
buttons = <IconButton icon={following ? 'user-times' : 'user-plus'} title={intl.formatMessage(following ? messages.unfollow : messages.follow)} onClick={this.handleFollow} active={following} />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (displayOnly) {
|
|
||||||
return (
|
|
||||||
<div className='account'>
|
|
||||||
<div className='account__wrapper'>
|
|
||||||
<div className='account__display-name'>
|
|
||||||
<div className='account__avatar-wrapper'>
|
|
||||||
<Avatar account={account} size={36} />
|
|
||||||
</div>
|
|
||||||
<DisplayName account={account} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='account'>
|
<div className={[styles.default, styles.marginTop5PX, styles.marginBottom15PX].join(' ')}>
|
||||||
<div className='account__wrapper'>
|
<div className={[styles.default, styles.flexRow].join(' ')}>
|
||||||
<Link key={account.get('id')} className='account__display-name' title={account.get('acct')} to={`/${account.get('acct')}`}>
|
|
||||||
<div className='account__avatar-wrapper'><Avatar account={account} size={36} /></div>
|
<NavLink
|
||||||
|
className={[styles.default, styles.noUnderline].join(' ')}
|
||||||
|
title={account.get('acct')}
|
||||||
|
to={`/${account.get('acct')}`}
|
||||||
|
>
|
||||||
|
<Avatar account={account} size={52} />
|
||||||
|
</NavLink>
|
||||||
|
|
||||||
|
<div className={[styles.default, styles.alignItemsStart, styles.paddingHorizontal10PX].join(' ')}>
|
||||||
|
<NavLink
|
||||||
|
className={[styles.default, styles.noUnderline].join(' ')}
|
||||||
|
title={account.get('acct')}
|
||||||
|
to={`/${account.get('acct')}`}
|
||||||
|
>
|
||||||
<DisplayName account={account} />
|
<DisplayName account={account} />
|
||||||
</Link>
|
</NavLink>
|
||||||
|
<button className={[styles.default, styles.marginTop5PX, styles.colorBrand, styles.text, styles.cursorPointer, styles.fontSize14PX, styles.circle, styles.border1PX, styles.borderColorBrand, styles.paddingHorizontal20PX, styles.paddingVertical5PX].join(' ')}>
|
||||||
|
{intl.formatMessage(messages.follow)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button className={[styles.default, styles.marginLeftAuto, styles.paddingVertical2PX, styles.cursorPointer].join(' ')}>
|
||||||
|
<Icon width='14px' height='14px' />
|
||||||
|
</button>
|
||||||
|
|
||||||
<div className='account__relationship'>
|
|
||||||
{buttons}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import './gab_logo.scss'
|
|
||||||
|
|
||||||
const GabLogo = ({
|
const GabLogo = ({
|
||||||
width = '50px',
|
width = '50px',
|
||||||
height = '30px',
|
height = '30px',
|
|
@ -1,9 +0,0 @@
|
||||||
.gab-logo {
|
|
||||||
enable-background: new 0 0 50 30;
|
|
||||||
|
|
||||||
&__path {
|
|
||||||
fill-rule: evenodd;
|
|
||||||
clip-rule: evenodd;
|
|
||||||
fill: $gab-brand-default;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './gab_logo';
|
|
|
@ -4,8 +4,6 @@ import { makeGetAccount } from '../../selectors';
|
||||||
import Avatar from '../avatar';
|
import Avatar from '../avatar';
|
||||||
import DisplayName from '../display_name';
|
import DisplayName from '../display_name';
|
||||||
|
|
||||||
import './autosuggest_account.scss';
|
|
||||||
|
|
||||||
const makeMapStateToProps = () => {
|
const makeMapStateToProps = () => {
|
||||||
const getAccount = makeGetAccount();
|
const getAccount = makeGetAccount();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import unicodeMapping from '../emoji/emoji_unicode_mapping_light';
|
import unicodeMapping from '../emoji/emoji_unicode_mapping_light';
|
||||||
|
|
||||||
import './autosuggest_emoji.scss';
|
|
||||||
|
|
||||||
const assetHost = process.env.CDN_HOST || '';
|
const assetHost = process.env.CDN_HOST || '';
|
||||||
|
|
||||||
export default class AutosuggestEmoji extends PureComponent {
|
export default class AutosuggestEmoji extends PureComponent {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Fragment } from 'react'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
@ -7,8 +8,6 @@ import { textAtCursorMatchesToken } from '../../utils/cursor_token_match';
|
||||||
import AutosuggestAccount from '../autosuggest_account';
|
import AutosuggestAccount from '../autosuggest_account';
|
||||||
import AutosuggestEmoji from '../autosuggest_emoji';
|
import AutosuggestEmoji from '../autosuggest_emoji';
|
||||||
|
|
||||||
import './autosuggest_textbox.scss';
|
|
||||||
|
|
||||||
export default class AutosuggestTextbox extends ImmutablePureComponent {
|
export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -198,15 +197,13 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textarea) {
|
if (textarea) {
|
||||||
return [
|
return (
|
||||||
<div className='autosuggest-textarea__wrapper' key='autosuggest-textarea__wrapper'>
|
<Fragment>
|
||||||
<div className='autosuggest-textarea'>
|
<div className={[styles.default].join(' ')}>
|
||||||
<label>
|
<div className={[styles.default, styles.marginLeft5PX].join(' ')}>
|
||||||
<span style={{ display: 'none' }}>{placeholder}</span>
|
|
||||||
|
|
||||||
<Textarea
|
<Textarea
|
||||||
inputRef={this.setTextbox}
|
inputRef={this.setTextbox}
|
||||||
className='autosuggest-textarea__textarea'
|
className={[styles.default, styles.backgroundWhite, styles.lineHeight125, styles.resizeNone, styles.paddingVertical15PX, styles.outlineNone, styles.fontSize16PX, styles.text, styles.displayBlock].join(' ')}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
|
@ -220,16 +217,16 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||||
style={style}
|
style={style}
|
||||||
aria-autocomplete='list'
|
aria-autocomplete='list'
|
||||||
/>
|
/>
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
{children}
|
{children}
|
||||||
</div>,
|
</div>
|
||||||
<div className='autosuggest-textarea__suggestions-wrapper' key='autosuggest-textarea__suggestions-wrapper'>
|
<div className='autosuggest-textarea__suggestions-wrapper'>
|
||||||
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
|
<div className={`autosuggest-textarea__suggestions ${suggestionsHidden || suggestions.isEmpty() ? '' : 'autosuggest-textarea__suggestions--visible'}`}>
|
||||||
{suggestions.map(this.renderSuggestion)}
|
{suggestions.map(this.renderSuggestion)}
|
||||||
</div>
|
</div>
|
||||||
</div>,
|
</div>
|
||||||
];
|
</Fragment>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable'
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames'
|
||||||
import { autoPlayGif } from '../../initial_state';
|
import { autoPlayGif } from '../../initial_state'
|
||||||
|
|
||||||
import './avatar.scss';
|
|
||||||
|
|
||||||
export default class Avatar extends ImmutablePureComponent {
|
export default class Avatar extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
@ -13,57 +11,53 @@ export default class Avatar extends ImmutablePureComponent {
|
||||||
size: PropTypes.number,
|
size: PropTypes.number,
|
||||||
inline: PropTypes.bool,
|
inline: PropTypes.bool,
|
||||||
animate: PropTypes.bool,
|
animate: PropTypes.bool,
|
||||||
};
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
account: ImmutableMap(),
|
account: ImmutableMap(),
|
||||||
animate: autoPlayGif,
|
animate: autoPlayGif,
|
||||||
inline: false,
|
inline: false,
|
||||||
};
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
hovering: false,
|
hovering: false,
|
||||||
sameImg: this.props.account.get('avatar') === this.props.account.get('avatar_static'),
|
sameImg: this.props.account.get('avatar') === this.props.account.get('avatar_static'),
|
||||||
};
|
}
|
||||||
|
|
||||||
handleMouseEnter = () => {
|
handleMouseEnter = () => {
|
||||||
if (this.props.animate || this.state.sameImg) return;
|
if (this.props.animate || this.state.sameImg) return
|
||||||
|
|
||||||
this.setState({ hovering: true });
|
this.setState({ hovering: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMouseLeave = () => {
|
handleMouseLeave = () => {
|
||||||
if (this.props.animate || this.state.sameImg) return;
|
if (this.props.animate || this.state.sameImg) return
|
||||||
|
|
||||||
this.setState({ hovering: false });
|
this.setState({ hovering: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { account, size, animate, inline } = this.props;
|
const { account, size, animate, inline } = this.props
|
||||||
const { hovering } = this.state;
|
const { hovering } = this.state
|
||||||
|
|
||||||
// : TODO : remove inline and change all avatars to be sized using css
|
// : TODO : remove inline and change all avatars to be sized using css
|
||||||
const style = !size ? {} : {
|
const style = !size ? {} : {
|
||||||
width: `${size}px`,
|
width: `${size}px`,
|
||||||
height: `${size}px`,
|
height: `${size}px`,
|
||||||
};
|
}
|
||||||
|
|
||||||
const theSrc = account.get((hovering || animate) ? 'avatar' : 'avatar_static');
|
const theSrc = account.get((hovering || animate) ? 'avatar' : 'avatar_static')
|
||||||
|
|
||||||
const className = classNames('account__avatar', {
|
|
||||||
'account__avatar--inline': inline,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
className={className}
|
className={[styles.default, styles.circle].join(' ')}
|
||||||
onMouseEnter={this.handleMouseEnter}
|
onMouseEnter={this.handleMouseEnter}
|
||||||
onMouseLeave={this.handleMouseLeave}
|
onMouseLeave={this.handleMouseLeave}
|
||||||
style={style}
|
style={style}
|
||||||
src={theSrc}
|
src={theSrc}
|
||||||
alt={account.get('display_name')}
|
alt={account.get('display_name')}
|
||||||
/>
|
/>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { autoPlayGif } from '../../initial_state';
|
import { autoPlayGif } from '../../initial_state';
|
||||||
|
|
||||||
import './avatar_overlay.scss';
|
|
||||||
|
|
||||||
export default class AvatarOverlay extends ImmutablePureComponent {
|
export default class AvatarOverlay extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
import './badge.scss';
|
|
||||||
|
|
||||||
export default class Badge extends PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
type: PropTypes.oneOf([
|
|
||||||
'pro',
|
|
||||||
'donor',
|
|
||||||
'investor',
|
|
||||||
]).isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { type } = this.props;
|
|
||||||
|
|
||||||
if (!type) return null;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span className={`badge badge--${type}`}>
|
|
||||||
{type.toUpperCase()}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,23 +0,0 @@
|
||||||
.badge {
|
|
||||||
text-transform: uppercase;
|
|
||||||
padding: 2px 6px;
|
|
||||||
border-radius: 2px;
|
|
||||||
margin: 0 5px 5px 0;
|
|
||||||
|
|
||||||
@include text-sizing(12px, 600, 1, center);
|
|
||||||
|
|
||||||
&--pro {
|
|
||||||
background-color: blueviolet;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--investor {
|
|
||||||
background-color: gold;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
&--donor {
|
|
||||||
background-color: lightgreen;
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './badge';
|
|
|
@ -3,8 +3,6 @@ import Column from '../column';
|
||||||
import { ColumnHeader } from '../column_header';
|
import { ColumnHeader } from '../column_header';
|
||||||
import IconButton from '../icon_button';
|
import IconButton from '../icon_button';
|
||||||
|
|
||||||
import './bundle_column_error.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id: 'bundle_column_error.title', defaultMessage: 'Network error' },
|
title: { id: 'bundle_column_error.title', defaultMessage: 'Network error' },
|
||||||
body: { id: 'bundle_column_error.body', defaultMessage: 'Something went wrong while loading this component.' },
|
body: { id: 'bundle_column_error.body', defaultMessage: 'Something went wrong while loading this component.' },
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import IconButton from '../icon_button';
|
import IconButton from '../icon_button';
|
||||||
|
|
||||||
import './bundle_modal_error.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
error: { id: 'bundle_modal_error.message', defaultMessage: 'Something went wrong while loading this component.' },
|
error: { id: 'bundle_modal_error.message', defaultMessage: 'Something went wrong while loading this component.' },
|
||||||
retry: { id: 'bundle_modal_error.retry', defaultMessage: 'Try again' },
|
retry: { id: 'bundle_modal_error.retry', defaultMessage: 'Try again' },
|
||||||
|
|
|
@ -56,10 +56,10 @@ export default class Button extends PureComponent {
|
||||||
colorWhite: 1,
|
colorWhite: 1,
|
||||||
circle: 1,
|
circle: 1,
|
||||||
cursorPointer: 1,
|
cursorPointer: 1,
|
||||||
width100PC: 1,
|
|
||||||
textAlignCenter: 1,
|
textAlignCenter: 1,
|
||||||
paddingVertical10PX: 1,
|
paddingVertical10PX: 1,
|
||||||
paddingHorizontal15PX: 1,
|
paddingHorizontal15PX: 1,
|
||||||
|
width100PC: block,
|
||||||
backgroundColorBrand: !hovering,
|
backgroundColorBrand: !hovering,
|
||||||
backgroundColorBrandDark: hovering,
|
backgroundColorBrandDark: hovering,
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { isMobile } from '../../utils/is_mobile';
|
||||||
import { ColumnHeader } from '../column_header';
|
import { ColumnHeader } from '../column_header';
|
||||||
import ColumnBackButton from '../column_back_button';
|
import ColumnBackButton from '../column_back_button';
|
||||||
|
|
||||||
import './column.scss';
|
|
||||||
|
|
||||||
export default class Column extends PureComponent {
|
export default class Column extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { FormattedMessage } from 'react-intl';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
|
|
||||||
import './column_back_button.scss';
|
|
||||||
|
|
||||||
export default class ColumnBackButton extends PureComponent {
|
export default class ColumnBackButton extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
|
|
|
@ -3,8 +3,6 @@ import classNames from 'classnames';
|
||||||
import { injectIntl, defineMessages } from 'react-intl';
|
import { injectIntl, defineMessages } from 'react-intl';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
|
|
||||||
import './column_header.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
||||||
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
|
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
|
||||||
|
|
|
@ -7,8 +7,6 @@ import { createSelector } from 'reselect';
|
||||||
import { fetchLists } from '../../actions/lists';
|
import { fetchLists } from '../../actions/lists';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
|
|
||||||
import './column_header.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
show: { id: 'column_header.show_settings', defaultMessage: 'Show settings' },
|
||||||
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
|
hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' },
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { Link } from 'react-router-dom';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
|
|
||||||
import './column_header_setting_button.scss';
|
|
||||||
|
|
||||||
export default class ColumnHeaderSettingButton extends PureComponent {
|
export default class ColumnHeaderSettingButton extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import Column from '../column';
|
import Column from '../column';
|
||||||
|
|
||||||
import './column_indicator.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
loading: { id: 'loading_indicator.label', defaultMessage: 'Loading...' },
|
loading: { id: 'loading_indicator.label', defaultMessage: 'Loading...' },
|
||||||
missing: { id: 'missing_indicator.sublabel', defaultMessage: 'This resource could not be found.' },
|
missing: { id: 'missing_indicator.sublabel', defaultMessage: 'This resource could not be found.' },
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import Button from '../button';
|
import Button from '../button';
|
||||||
|
|
||||||
import './column_inline_form.scss';
|
|
||||||
|
|
||||||
export default class ColumnInlineForm extends PureComponent {
|
export default class ColumnInlineForm extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import Icon from '../../components/icon';
|
import Icon from '../../components/icon';
|
||||||
|
|
||||||
import './column_link.scss';
|
|
||||||
|
|
||||||
export default class ColumnLink extends PureComponent {
|
export default class ColumnLink extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import './column_settings_heading.scss';
|
|
||||||
|
|
||||||
export default class ColumnSettingsHeading extends PureComponent {
|
export default class ColumnSettingsHeading extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
heading: PropTypes.object.isRequired,
|
heading: PropTypes.object.isRequired,
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import './column_subheading.scss';
|
|
||||||
|
|
||||||
export default class ColumnSubheading extends PureComponent {
|
export default class ColumnSubheading extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
text: PropTypes.string.isRequired,
|
text: PropTypes.string.isRequired,
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
import Icon from './icon';
|
||||||
|
|
||||||
|
export default class DisplayName extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
account: ImmutablePropTypes.map.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { account } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span className={[styles.default, styles.flexRow, styles.maxWidth100PC, styles.alignItemsCenter].join(' ')}>
|
||||||
|
<bdi className={[styles.text, styles.whiteSpaceNoWrap, styles.textOverflowEllipsis].join(' ')}>
|
||||||
|
<strong
|
||||||
|
className={[styles.text, styles.overflowWrapBreakWord, styles.whiteSpaceNoWrap, styles.fontSize15PX, styles.fontWeightBold, styles.colorBlack, styles.lineHeight125, styles.marginRight2PX].join(' ')}
|
||||||
|
dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }}
|
||||||
|
/>
|
||||||
|
</bdi>
|
||||||
|
{
|
||||||
|
account.get('is_verified') &&
|
||||||
|
<Icon id='verified' width='15px' height='15px' className={[styles.default]} title='Verified Account' />
|
||||||
|
/*<Icon id='verified' width='15px' height='15px' className={[styles.default]} title='PRO' />
|
||||||
|
<Icon id='verified' width='15px' height='15px' className={[styles.default]} title='Donor' />
|
||||||
|
<Icon id='verified' width='15px' height='15px' className={[styles.default]} title='Investor' />*/
|
||||||
|
}
|
||||||
|
<span className={[styles.text, styles.displayFlex, styles.flexNormal, styles.flexShrink1, styles.fontSize15PX, styles.overflowWrapBreakWord, styles.textOverflowEllipsis, styles.marginLeft5PX, styles.colorSubtle, styles.fontWeightNormal, styles.lineHeight125].join(' ')}>
|
||||||
|
@{account.get('acct')}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,27 +0,0 @@
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
|
||||||
import VerifiedIcon from '../verified_icon';
|
|
||||||
|
|
||||||
import './display_name.scss';
|
|
||||||
|
|
||||||
export default class DisplayName extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
account: ImmutablePropTypes.map.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { account } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span className='display-name'>
|
|
||||||
<bdi>
|
|
||||||
<strong className='display-name__html' dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }} />
|
|
||||||
</bdi>
|
|
||||||
{account.get('is_verified') && <VerifiedIcon />}
|
|
||||||
<span className='display-name__account'>@{account.get('acct')}</span>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
.display-name {
|
|
||||||
display: block;
|
|
||||||
max-width: 100%;
|
|
||||||
|
|
||||||
@include text-overflow(break-word);
|
|
||||||
|
|
||||||
&__html {
|
|
||||||
font-weight: 600;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__account {
|
|
||||||
margin-left: 5px;
|
|
||||||
font-size: 15px;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './display_name';
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import IconButton from '../icon_button';
|
import IconButton from '../icon_button';
|
||||||
|
|
||||||
import './domain.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' },
|
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' },
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,8 +6,6 @@ import spring from 'react-motion/lib/spring';
|
||||||
import Motion from '../../features/ui/util/optional_motion';
|
import Motion from '../../features/ui/util/optional_motion';
|
||||||
import IconButton from '../icon_button';
|
import IconButton from '../icon_button';
|
||||||
|
|
||||||
import './dropdown_menu.scss';
|
|
||||||
|
|
||||||
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
|
const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false;
|
||||||
let id = 0;
|
let id = 0;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import './error_boundary.scss';
|
|
||||||
|
|
||||||
export default class ErrorBoundary extends PureComponent {
|
export default class ErrorBoundary extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
import './extended_video_player.scss';
|
|
||||||
|
|
||||||
export default class ExtendedVideoPlayer extends PureComponent {
|
export default class ExtendedVideoPlayer extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import ComposeIcon from './assets/compose_icon';
|
import ComposeIcon from './assets/compose_icon';
|
||||||
|
|
||||||
import './floating_action_button.scss';
|
|
||||||
|
|
||||||
export default class FloatingActionButton extends Component {
|
export default class FloatingActionButton extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
|
|
|
@ -3,8 +3,6 @@ import { FormattedMessage, injectIntl } from 'react-intl';
|
||||||
import NotificationCounter from '../notification_counter';
|
import NotificationCounter from '../notification_counter';
|
||||||
import { me } from '../../initial_state';
|
import { me } from '../../initial_state';
|
||||||
|
|
||||||
import './footer_bar.scss';
|
|
||||||
|
|
||||||
const links = [
|
const links = [
|
||||||
<NavLink key='pr1' className='footer-bar__link' to='/home' data-preview-title-id='column.home'>
|
<NavLink key='pr1' className='footer-bar__link' to='/home' data-preview-title-id='column.home'>
|
||||||
<i className='tabs-bar__link__icon home'/>
|
<i className='tabs-bar__link__icon home'/>
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
import { Link, NavLink } from 'react-router-dom'
|
import { NavLink } from 'react-router-dom'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { injectIntl, defineMessages } from 'react-intl'
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
import Avatar from './avatar'
|
|
||||||
import Button from './button'
|
import Button from './button'
|
||||||
import Icon from './icon'
|
import Icon from './icon'
|
||||||
import DisplayName from './display_name'
|
|
||||||
import { closeSidebar } from '../actions/sidebar'
|
import { closeSidebar } from '../actions/sidebar'
|
||||||
import { shortNumberFormat } from '../utils/numbers'
|
|
||||||
import { me } from '../initial_state'
|
import { me } from '../initial_state'
|
||||||
import { makeGetAccount } from '../selectors'
|
import { makeGetAccount } from '../selectors'
|
||||||
// import ProgressPanel from './progress_panel'
|
// import ProgressPanel from './progress_panel'
|
||||||
|
@ -87,18 +84,6 @@ class Header extends ImmutablePureComponent {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseEnterLinkFooterItem = (i) => {
|
|
||||||
this.setState({
|
|
||||||
hoveringItemIndex: i,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
onMouseLeaveLinkFooterItem = () => {
|
|
||||||
this.setState({
|
|
||||||
hoveringItemIndex: null,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSidebarClose = () => {
|
handleSidebarClose = () => {
|
||||||
this.props.onClose()
|
this.props.onClose()
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -119,44 +104,73 @@ class Header extends ImmutablePureComponent {
|
||||||
// 'sidebar-menu__root--visible': sidebarOpen,
|
// 'sidebar-menu__root--visible': sidebarOpen,
|
||||||
// })
|
// })
|
||||||
|
|
||||||
const cx = classNames.bind(styles)
|
|
||||||
|
|
||||||
const moreIcon = moreOpen ? 'minus' : 'plus'
|
const moreIcon = moreOpen ? 'minus' : 'plus'
|
||||||
const moreContainerStyle = { display: moreOpen ? 'block' : 'none' }
|
const moreContainerStyle = { display: moreOpen ? 'block' : 'none' }
|
||||||
|
|
||||||
const sidebarItems = [
|
const menuItems = [
|
||||||
{
|
{
|
||||||
name: 'Home',
|
title: 'Home',
|
||||||
icon: <NotificationsIcon />,
|
icon: <NotificationsIcon />,
|
||||||
to: '/',
|
to: '/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Notifications',
|
title: 'Notifications',
|
||||||
icon: <NotificationsIcon />,
|
icon: <NotificationsIcon />,
|
||||||
to: '/notifications',
|
to: '/notifications',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Groups',
|
title: 'Groups',
|
||||||
icon: <NotificationsIcon />,
|
icon: <NotificationsIcon />,
|
||||||
to: '/groups',
|
to: '/groups',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Lists',
|
title: 'Lists',
|
||||||
icon: <NotificationsIcon />,
|
icon: <NotificationsIcon />,
|
||||||
to: '/lists',
|
to: '/lists',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Chat',
|
title: 'Chat',
|
||||||
icon: <NotificationsIcon />,
|
icon: <NotificationsIcon />,
|
||||||
to: '/',
|
to: '/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Trends',
|
title: 'Profile',
|
||||||
|
icon: <NotificationsIcon />,
|
||||||
|
to: '/',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const shortcutItems = [
|
||||||
|
{
|
||||||
|
title: 'Meme Group',
|
||||||
icon: <NotificationsIcon />,
|
icon: <NotificationsIcon />,
|
||||||
to: '/',
|
to: '/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Profile',
|
title: 'Andrew',
|
||||||
|
icon: <NotificationsIcon />,
|
||||||
|
to: '/',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const exploreItems = [
|
||||||
|
{
|
||||||
|
title: 'Trends',
|
||||||
|
icon: <NotificationsIcon />,
|
||||||
|
to: '/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Dissenter',
|
||||||
|
icon: <NotificationsIcon />,
|
||||||
|
to: '/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Apps',
|
||||||
|
icon: <NotificationsIcon />,
|
||||||
|
to: '/',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Shop',
|
||||||
icon: <NotificationsIcon />,
|
icon: <NotificationsIcon />,
|
||||||
to: '/',
|
to: '/',
|
||||||
},
|
},
|
||||||
|
@ -166,186 +180,116 @@ class Header extends ImmutablePureComponent {
|
||||||
<header role='banner' className={[styles.default, styles.flexGrow1, styles.z3, styles.alignItemsEnd].join(' ')}>
|
<header role='banner' className={[styles.default, styles.flexGrow1, styles.z3, styles.alignItemsEnd].join(' ')}>
|
||||||
<div className={[styles.default, styles.width250PX].join(' ')}>
|
<div className={[styles.default, styles.width250PX].join(' ')}>
|
||||||
<div className={[styles.default, styles.positionFixed, styles.top0, styles.height100PC].join(' ')}>
|
<div className={[styles.default, styles.positionFixed, styles.top0, styles.height100PC].join(' ')}>
|
||||||
<div className={[styles.default, styles.height100PC, styles.width250PX, styles.paddingHorizontal20PX].join(' ')}>
|
<div className={[styles.default, styles.height100PC, styles.width250PX, styles.paddingHorizontal20PX, styles.marginVertical10PX].join(' ')}>
|
||||||
<h1 className={[styles.default].join(' ')}>
|
<h1 className={[styles.default].join(' ')}>
|
||||||
<NavLink to='/' aria-label='Gab' className={[styles.default, styles.noSelect, styles.noUnderline, styles.height50PX, styles.justifyContentCenter, styles.cursorPointer, styles.paddingHoizontal10PX].join(' ')}>
|
<NavLink to='/' aria-label='Gab' className={[styles.default, styles.noSelect, styles.noUnderline, styles.height50PX, styles.justifyContentCenter, styles.cursorPointer, styles.paddingHorizontal10PX].join(' ')}>
|
||||||
<GabLogo />
|
<GabLogo />
|
||||||
</NavLink>
|
</NavLink>
|
||||||
</h1>
|
</h1>
|
||||||
<nav aria-label='Primary' role='navigation' className={[styles.default, styles.width100PC].join(' ')}>
|
<div>
|
||||||
|
{ /* profile card */}
|
||||||
|
</div>
|
||||||
|
<nav aria-label='Primary' role='navigation' className={[styles.default, styles.width100PC, styles.marginBottom15PX].join(' ')}>
|
||||||
|
<span className={[styles.default, styles.text, styles.colorSubtle, styles.displayBlock, styles.fontSize13PX, styles.paddingVertical5PX, styles.marginTop10PX, styles.paddingHorizontal10PX, styles.fontWeight500].join(' ')}>Menu</span>
|
||||||
{
|
{
|
||||||
sidebarItems.map((sidebarItem, i) => {
|
menuItems.map((menuItem, i) => (
|
||||||
const containerClasses = cx({
|
<HeaderMenuItem {...menuItem} key={`header-item-menu-${i}`} />
|
||||||
default: 1,
|
))
|
||||||
maxWidth100PC: 1,
|
}
|
||||||
flexRow: 1,
|
<span className={[styles.default, styles.text, styles.colorSubtle, styles.displayBlock, styles.fontSize13PX, styles.paddingVertical5PX, styles.marginTop10PX, styles.paddingHorizontal10PX, styles.fontWeight500].join(' ')}>Shortcuts</span>
|
||||||
paddingVertical10PX: 1,
|
{
|
||||||
paddingHoizontal10PX: 1,
|
shortcutItems.map((shortcutItem, i) => (
|
||||||
circle: 1,
|
<HeaderMenuItem {...shortcutItem} key={`header-item-shortcut-${i}`} />
|
||||||
alignItemsCenter: 1,
|
))
|
||||||
backgroundColorBrandLightOpaque: hoveringItemIndex === i,
|
}
|
||||||
})
|
<span className={[styles.default, styles.text, styles.colorSubtle, styles.displayBlock, styles.fontSize13PX, styles.paddingVertical5PX, styles.marginTop10PX, styles.paddingHorizontal10PX, styles.fontWeight500].join(' ')}>Explore</span>
|
||||||
|
{
|
||||||
const textClasses = cx({
|
exploreItems.map((exploreItem, i) => (
|
||||||
default: 1,
|
<HeaderMenuItem {...exploreItem} key={`header-item-explore-${i}`} />
|
||||||
fontWeightBold: 1,
|
))
|
||||||
fontSize19PX: 1,
|
|
||||||
text: 1,
|
|
||||||
colorBrand: hoveringItemIndex === i,
|
|
||||||
colorBlack: hoveringItemIndex !== i,
|
|
||||||
})
|
|
||||||
|
|
||||||
const iconClasses = cx({
|
|
||||||
fillColorBrand: hoveringItemIndex === i,
|
|
||||||
fillColorBlack: hoveringItemIndex !== i,
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
|
||||||
<NavLink
|
|
||||||
to={sidebarItem.to}
|
|
||||||
key={`header-nav-item-${i}`}
|
|
||||||
onMouseEnter={() => this.onMouseEnterLinkFooterItem(i)}
|
|
||||||
onMouseLeave={() => this.onMouseLeaveLinkFooterItem(i)}
|
|
||||||
className={[styles.default, styles.noUnderline, styles.cursorPointer, styles.width100PC, styles.alignItemsStart, styles.flexGrow1].join(' ')}
|
|
||||||
>
|
|
||||||
<div className={containerClasses}>
|
|
||||||
<div className={[styles.default]}>
|
|
||||||
<NotificationsIcon className={iconClasses}/>
|
|
||||||
</div>
|
|
||||||
<div className={[styles.default, styles.paddingHorizontal20PX, styles.textOverflowEllipsis, styles.overflowWrapBreakWord, styles.displayInline].join(' ')}>
|
|
||||||
<span className={textClasses}>
|
|
||||||
{sidebarItem.name}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</NavLink>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
</nav>
|
</nav>
|
||||||
<Button className={[styles.paddingVertical15PX, styles.marginVertical5PX, styles.fontSize15PX, styles.fontWeightBold].join(' ')}>Gab</Button>
|
<Button className={[styles.paddingVertical15PX, styles.fontSize15PX, styles.fontWeightBold].join(' ')}>Gab</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
)
|
)
|
||||||
|
|
||||||
// return (
|
|
||||||
// <div className={classes}>
|
|
||||||
// <div className='sidebar-menu__wrapper' role='button' onClick={this.handleSidebarClose} />
|
|
||||||
// <div className='sidebar-menu'>
|
|
||||||
|
|
||||||
// <div className='sidebar-menu-header'>
|
|
||||||
// <span className='sidebar-menu-header__title'>Account Info</span>
|
|
||||||
// <IconButton title='close' onClick={this.handleSidebarClose} icon='close' className='sidebar-menu-header__btn' />
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// <div className='sidebar-menu__content'>
|
|
||||||
|
|
||||||
// <div className='sidebar-menu-profile'>
|
|
||||||
// <div className='sidebar-menu-profile__avatar'>
|
|
||||||
// <Link to={`/${acct}`} title={acct} onClick={this.handleSidebarClose}>
|
|
||||||
// <Avatar account={account} />
|
|
||||||
// </Link>
|
|
||||||
// </div>
|
|
||||||
// <div className='sidebar-menu-profile__name'>
|
|
||||||
// <DisplayName account={account} />
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// <div className='sidebar-menu-profile__stats'>
|
|
||||||
// <NavLink className='sidebar-menu-profile-stat' to={`/${acct}/followers`} onClick={this.handleSidebarClose} title={intl.formatNumber(account.get('followers_count'))}>
|
|
||||||
// <strong className='sidebar-menu-profile-stat__value'>{shortNumberFormat(account.get('followers_count'))}</strong>
|
|
||||||
// <span className='sidebar-menu-profile-stat__label'>{intl.formatMessage(messages.followers)}</span>
|
|
||||||
// </NavLink>
|
|
||||||
// <NavLink className='sidebar-menu-profile-stat' to={`/${acct}/following`} onClick={this.handleSidebarClose} title={intl.formatNumber(account.get('following_count'))}>
|
|
||||||
// <strong className='sidebar-menu-profile-stat__value'>{shortNumberFormat(account.get('following_count'))}</strong>
|
|
||||||
// <span className='sidebar-menu-profile-stat__label'>{intl.formatMessage(messages.follows)}</span>
|
|
||||||
// </NavLink>
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// <div className='sidebar-menu__section'>
|
|
||||||
// { /* <ProgressPanel /> */ }
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// <div className='sidebar-menu__section sidebar-menu__section--borderless'>
|
|
||||||
// <NavLink className='sidebar-menu-item' to={`/${acct}`} onClick={this.handleSidebarClose}>
|
|
||||||
// <Icon id='user' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.profile)}</span>
|
|
||||||
// </NavLink>
|
|
||||||
// {
|
|
||||||
// !isPro &&
|
|
||||||
// <a className='sidebar-menu-item' href='https://pro.gab.com'>
|
|
||||||
// <Icon id='arrow-up' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.pro)}</span>
|
|
||||||
// </a>
|
|
||||||
// }
|
|
||||||
// <a className='sidebar-menu-item' href='https://shop.dissenter.com/category/donations'>
|
|
||||||
// <Icon id='heart' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.donate)}</span>
|
|
||||||
// </a>
|
|
||||||
// <a className='sidebar-menu-item' href='https://shop.dissenter.com'>
|
|
||||||
// <Icon id='shopping-cart' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.shop)}</span>
|
|
||||||
// </a>
|
|
||||||
// <a className='sidebar-menu-item' href='https://trends.gab.com'>
|
|
||||||
// <Icon id='signal' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.trends)}</span>
|
|
||||||
// </a>
|
|
||||||
// <NavLink className='sidebar-menu-item' to='/search' onClick={this.handleSidebarClose}>
|
|
||||||
// <Icon id='search' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.search)}</span>
|
|
||||||
// </NavLink>
|
|
||||||
// <a className='sidebar-menu-item' href='/settings/preferences'>
|
|
||||||
// <Icon id='cog' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.preferences)}</span>
|
|
||||||
// </a>
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// <div className='sidebar-menu__section'>
|
|
||||||
// <div className='sidebar-menu-item' onClick={this.toggleMore} role='button'>
|
|
||||||
// <Icon id={moreIcon} fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.more)}</span>
|
|
||||||
// </div>
|
|
||||||
// <div style={moreContainerStyle}>
|
|
||||||
// <NavLink className='sidebar-menu-item' to='/lists' onClick={this.handleSidebarClose}>
|
|
||||||
// <Icon id='list' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.lists)}</span>
|
|
||||||
// </NavLink>
|
|
||||||
// <NavLink className='sidebar-menu-item' to='/follow_requests' onClick={this.handleSidebarClose}>
|
|
||||||
// <Icon id='user-plus' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.follow_requests)}</span>
|
|
||||||
// </NavLink>
|
|
||||||
// <NavLink className='sidebar-menu-item' to='/blocks' onClick={this.handleSidebarClose}>
|
|
||||||
// <Icon id='ban' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.blocks)}</span>
|
|
||||||
// </NavLink>
|
|
||||||
// <NavLink className='sidebar-menu-item' to='/domain_blocks' onClick={this.handleSidebarClose}>
|
|
||||||
// <Icon id='sitemap' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.domain_blocks)}</span>
|
|
||||||
// </NavLink>
|
|
||||||
// <NavLink className='sidebar-menu-item' to='/mutes' onClick={this.handleSidebarClose}>
|
|
||||||
// <Icon id='times-circle' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.mutes)}</span>
|
|
||||||
// </NavLink>
|
|
||||||
// <a className='sidebar-menu-item' href='/filters'>
|
|
||||||
// <Icon id='filter' fixedWidth />
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.filters)}</span>
|
|
||||||
// </a>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// <div className='sidebar-menu__section'>
|
|
||||||
// <a className='sidebar-menu-item' href='/auth/sign_out' data-method='delete'>
|
|
||||||
// <span className='sidebar-menu-item__title'>{intl.formatMessage(messages.logout)}</span>
|
|
||||||
// </a>
|
|
||||||
// </div>
|
|
||||||
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// </div>
|
|
||||||
// )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class HeaderMenuItem extends PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
to: PropTypes.string,
|
||||||
|
active: PropTypes.bool,
|
||||||
|
icon: PropTypes.node,
|
||||||
|
title: PropTypes.string,
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
hovering: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseEnter = () => {
|
||||||
|
this.setState({ hovering: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseLeave = () => {
|
||||||
|
this.setState({ hovering: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { to, active, icon, title } = this.props
|
||||||
|
const { hovering } = this.state
|
||||||
|
|
||||||
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
|
const shouldShowActive = hovering || active
|
||||||
|
|
||||||
|
const containerClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
maxWidth100PC: 1,
|
||||||
|
width100PC: 1,
|
||||||
|
flexRow: 1,
|
||||||
|
paddingVertical5PX: 1,
|
||||||
|
paddingHorizontal10PX: 1,
|
||||||
|
alignItemsCenter: 1,
|
||||||
|
// border1PX: shouldShowActive,
|
||||||
|
// borderColorSubtle: shouldShowActive,
|
||||||
|
backgroundWhite: shouldShowActive,
|
||||||
|
})
|
||||||
|
|
||||||
|
const textClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
fontWeightNormal: 1,
|
||||||
|
fontSize15PX: 1,
|
||||||
|
text: 1,
|
||||||
|
colorBrand: shouldShowActive,
|
||||||
|
colorBlack: !hovering && !active,
|
||||||
|
})
|
||||||
|
|
||||||
|
const iconClasses = cx({
|
||||||
|
fillColorBrand: shouldShowActive,
|
||||||
|
fillColorBlack: !hovering && !active,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavLink
|
||||||
|
to={to}
|
||||||
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
|
className={[styles.default, styles.noUnderline, styles.cursorPointer, styles.width100PC, styles.alignItemsStart, styles.flexGrow1].join(' ')}
|
||||||
|
>
|
||||||
|
<div className={containerClasses}>
|
||||||
|
<div className={[styles.default]}>
|
||||||
|
<NotificationsIcon className={iconClasses} width='16px' height='16px' />
|
||||||
|
</div>
|
||||||
|
<div className={[styles.default, styles.paddingHorizontal10PX, styles.textOverflowEllipsis, styles.overflowWrapBreakWord, styles.displayInline].join(' ')}>
|
||||||
|
<span className={textClasses}>{title}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</NavLink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import './icon.scss';
|
|
||||||
export default class Icon extends PureComponent {
|
export default class Icon extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -3,8 +3,6 @@ import spring from 'react-motion/lib/spring';
|
||||||
import Motion from '../../features/ui/util/optional_motion';
|
import Motion from '../../features/ui/util/optional_motion';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
|
|
||||||
import './icon_button.scss';
|
|
||||||
|
|
||||||
export default class IconButton extends PureComponent {
|
export default class IconButton extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
@ -23,6 +21,8 @@ export default class IconButton extends PureComponent {
|
||||||
overlay: PropTypes.bool,
|
overlay: PropTypes.bool,
|
||||||
tabIndex: PropTypes.string,
|
tabIndex: PropTypes.string,
|
||||||
text: PropTypes.string,
|
text: PropTypes.string,
|
||||||
|
width: PropTypes.string,
|
||||||
|
height: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
|
@ -64,6 +64,8 @@ export default class IconButton extends PureComponent {
|
||||||
tabIndex,
|
tabIndex,
|
||||||
title,
|
title,
|
||||||
text,
|
text,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const classes = classNames(className, 'icon-button', {
|
const classes = classNames(className, 'icon-button', {
|
||||||
|
@ -73,8 +75,6 @@ export default class IconButton extends PureComponent {
|
||||||
overlayed: overlay,
|
overlayed: overlay,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Perf optimization: avoid unnecessary <Motion> components unless we actually need to animate.
|
|
||||||
if (!animate) {
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
aria-label={title}
|
aria-label={title}
|
||||||
|
@ -87,32 +87,10 @@ export default class IconButton extends PureComponent {
|
||||||
tabIndex={tabIndex}
|
tabIndex={tabIndex}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
>
|
>
|
||||||
<Icon id={icon} fixedWidth aria-hidden='true' />
|
<Icon id={icon} fixedWidth aria-hidden='true' width={width} height={height} />
|
||||||
{!!text && text}
|
{!!text && text}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
|
||||||
<Motion defaultStyle={{ rotate: active ? -360 : 0 }} style={{ rotate: animate ? spring(active ? -360 : 0, { stiffness: 120, damping: 7 }) : 0 }}>
|
|
||||||
{({ rotate }) => (
|
|
||||||
<button
|
|
||||||
aria-label={title}
|
|
||||||
aria-pressed={pressed}
|
|
||||||
aria-expanded={expanded}
|
|
||||||
title={title}
|
|
||||||
className={classes}
|
|
||||||
onClick={this.handleClick}
|
|
||||||
style={style}
|
|
||||||
tabIndex={tabIndex}
|
|
||||||
disabled={disabled}
|
|
||||||
>
|
|
||||||
<Icon id={icon} style={{ transform: `rotate(${rotate}deg)` }} fixedWidth aria-hidden='true' />
|
|
||||||
{!!text && text}
|
|
||||||
</button>
|
|
||||||
)}
|
|
||||||
</Motion>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ import classNames from 'classnames';
|
||||||
import { LoadingBar } from 'react-redux-loading-bar';
|
import { LoadingBar } from 'react-redux-loading-bar';
|
||||||
import ZoomableImage from '../zoomable_image';
|
import ZoomableImage from '../zoomable_image';
|
||||||
|
|
||||||
import './image_loader.scss';
|
|
||||||
|
|
||||||
export default class ImageLoader extends PureComponent {
|
export default class ImageLoader extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { is } from 'immutable';
|
||||||
import scheduleIdleTask from '../../utils/schedule_idle_task';
|
import scheduleIdleTask from '../../utils/schedule_idle_task';
|
||||||
import getRectFromEntry from '../../utils/get_rect_from_entry';
|
import getRectFromEntry from '../../utils/get_rect_from_entry';
|
||||||
|
|
||||||
import './intersection_observer_article.scss';
|
|
||||||
|
|
||||||
// Diff these props in the "rendered" state
|
// Diff these props in the "rendered" state
|
||||||
const updateOnPropsForRendered = ['id', 'index', 'listLength'];
|
const updateOnPropsForRendered = ['id', 'index', 'listLength'];
|
||||||
// Diff these props in the "unrendered" state
|
// Diff these props in the "unrendered" state
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
article {
|
article {
|
||||||
// TEMPORARY - content of columns may be significantly altered
|
// TEMPORARY - content of columns may be significantly altered
|
||||||
background: $gab-background-container;
|
// background: $gab-background-container;
|
||||||
}
|
}
|
|
@ -109,7 +109,7 @@ class LinkFooter extends PureComponent {
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.default}>
|
<div className={[styles.default, styles.paddingHorizontal10PX].join(' ')}>
|
||||||
<nav aria-label='Footer' role='navigation' className={[styles.default, styles.flexWrap, styles.flexRow].join(' ')}>
|
<nav aria-label='Footer' role='navigation' className={[styles.default, styles.flexWrap, styles.flexRow].join(' ')}>
|
||||||
{
|
{
|
||||||
linkFooterItems.map((linkFooterItem, i) => {
|
linkFooterItems.map((linkFooterItem, i) => {
|
||||||
|
@ -121,6 +121,7 @@ class LinkFooter extends PureComponent {
|
||||||
marginVertical5PX: 1,
|
marginVertical5PX: 1,
|
||||||
paddingRight15PX: 1,
|
paddingRight15PX: 1,
|
||||||
cursorPointer: 1,
|
cursorPointer: 1,
|
||||||
|
backgroundTransparent: 1,
|
||||||
colorSubtle: i !== hoveringItemIndex,
|
colorSubtle: i !== hoveringItemIndex,
|
||||||
noUnderline: i !== hoveringItemIndex,
|
noUnderline: i !== hoveringItemIndex,
|
||||||
colorBlack: i === hoveringItemIndex,
|
colorBlack: i === hoveringItemIndex,
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { injectIntl, defineMessages } from 'react-intl';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
|
|
||||||
import './load_more.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
load_more: { id: 'status.load_more', defaultMessage: 'Load more' },
|
load_more: { id: 'status.load_more', defaultMessage: 'Load more' },
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,8 +9,6 @@ import { isIOS } from '../../utils/is_mobile';
|
||||||
import { isPanoramic, isPortrait, isNonConformingRatio, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio';
|
import { isPanoramic, isPortrait, isNonConformingRatio, minimumAspectRatio, maximumAspectRatio } from '../../utils/media_aspect_ratio';
|
||||||
import IconButton from '../icon_button';
|
import IconButton from '../icon_button';
|
||||||
|
|
||||||
import './media_gallery.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' },
|
toggle_visible: { id: 'media_gallery.toggle_visible', defaultMessage: 'Toggle visibility' },
|
||||||
warning: { id: 'status.sensitive_warning', defaultMessage: 'Sensitive content' },
|
warning: { id: 'status.sensitive_warning', defaultMessage: 'Sensitive content' },
|
||||||
|
|
|
@ -5,8 +5,6 @@ import { changeUploadCompose } from '../../../actions/compose';
|
||||||
import { getPointerPosition } from '../../../utils/element_position';
|
import { getPointerPosition } from '../../../utils/element_position';
|
||||||
import ImageLoader from '../../image_loader';
|
import ImageLoader from '../../image_loader';
|
||||||
|
|
||||||
import './focal_point_modal.scss';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { id }) => ({
|
const mapStateToProps = (state, { id }) => ({
|
||||||
media: state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id),
|
media: state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id),
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import IconButton from '../../icon_button';
|
import IconButton from '../../icon_button';
|
||||||
|
|
||||||
import './hotkeys_modal.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'keyboard_shortcuts.heading', defaultMessage: 'Keyboard Shortcuts' },
|
heading: { id: 'keyboard_shortcuts.heading', defaultMessage: 'Keyboard Shortcuts' },
|
||||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||||
|
|
|
@ -9,8 +9,6 @@ import IconButton from '../../icon_button';
|
||||||
import ImageLoader from '../../image_loader';
|
import ImageLoader from '../../image_loader';
|
||||||
import Icon from '../../icon';
|
import Icon from '../../icon';
|
||||||
|
|
||||||
import './media_modal.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||||
previous: { id: 'lightbox.previous', defaultMessage: 'Previous' },
|
previous: { id: 'lightbox.previous', defaultMessage: 'Previous' },
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import IconButton from '../../icon_button';
|
import IconButton from '../../icon_button';
|
||||||
|
|
||||||
import './unauthorized_modal.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||||
signup: {id: 'unauthorized_modal.title', defaultMessage: 'Sign up for Gab' },
|
signup: {id: 'unauthorized_modal.title', defaultMessage: 'Sign up for Gab' },
|
||||||
|
|
|
@ -3,8 +3,6 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
import Video from '../../../features/video';
|
import Video from '../../../features/video';
|
||||||
|
|
||||||
import './video_modal.scss';
|
|
||||||
|
|
||||||
export const previewState = 'previewVideoModal';
|
export const previewState = 'previewVideoModal';
|
||||||
|
|
||||||
export default class VideoModal extends ImmutablePureComponent {
|
export default class VideoModal extends ImmutablePureComponent {
|
||||||
|
|
|
@ -3,8 +3,6 @@ import classNames from 'classnames';
|
||||||
import { openModal } from '../../actions/modal';
|
import { openModal } from '../../actions/modal';
|
||||||
import { cancelReplyCompose } from '../../actions/compose';
|
import { cancelReplyCompose } from '../../actions/compose';
|
||||||
|
|
||||||
import './modal_base.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
confirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
confirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import ColumnIndicator from '../column_indicator';
|
import ColumnIndicator from '../column_indicator';
|
||||||
|
|
||||||
import './modal_loading.scss';
|
|
||||||
|
|
||||||
// Keep the markup in sync with <BundleModalError />
|
// Keep the markup in sync with <BundleModalError />
|
||||||
// (make sure they have the same dimensions)
|
// (make sure they have the same dimensions)
|
||||||
export default class ModalLoading extends PureComponent {
|
export default class ModalLoading extends PureComponent {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { shortNumberFormat } from '../../utils/numbers';
|
import { shortNumberFormat } from '../../utils/numbers';
|
||||||
|
|
||||||
import './notification_counter.scss';
|
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
count: state.getIn(['notifications', 'unread']),
|
count: state.getIn(['notifications', 'unread']),
|
||||||
});
|
});
|
||||||
|
|
|
@ -11,11 +11,11 @@ export default class PageLayout extends PureComponent {
|
||||||
const right = layout.RIGHT || null
|
const right = layout.RIGHT || null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[styles.default, styles.flexRow, styles.width100PC].join(' ')}>
|
<div className={[styles.default, styles.flexRow, styles.width100PC, styles.backgroundColorSubtle3].join(' ')}>
|
||||||
<Header />
|
<Header />
|
||||||
<main role='main' className={[styles.default, styles.flexShrink1, styles.flexGrow1, styles.flexRow].join(' ')}>
|
<main role='main' className={[styles.default, styles.flexShrink1, styles.flexGrow1, styles.flexRow].join(' ')}>
|
||||||
<div className={[styles.default, styles.width1015PX, styles.flexRow, styles.justifyContentSpaceBetween].join(' ')}>
|
<div className={[styles.default, styles.width1015PX, styles.flexRow, styles.justifyContentSpaceBetween].join(' ')}>
|
||||||
<div className={[styles.default, styles.width660PX, styles.z1, styles.borderColorSubtle, styles.borderLeft1PX, styles.borderRight1PX].join(' ')}>
|
<div className={[styles.default, styles.width670PX, styles.z1].join(' ')}>
|
||||||
<div className={styles.default}>
|
<div className={styles.default}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
import { Fragment } from 'react'
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
|
import { NavLink } from 'react-router-dom'
|
||||||
|
import classNames from 'classnames/bind'
|
||||||
|
import { shortNumberFormat } from '../../utils/numbers'
|
||||||
|
import PanelLayout from './panel_layout'
|
||||||
|
import Icon from '../icon'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: { id: 'groups.sidebar-panel.title', defaultMessage: 'Groups you\'re in' },
|
||||||
|
show_all: { id: 'groups.sidebar-panel.show_all', defaultMessage: 'Show all' },
|
||||||
|
all: { id: 'groups.sidebar-panel.all', defaultMessage: 'All' },
|
||||||
|
new_statuses: { id: 'groups.sidebar-panel.item.view', defaultMessage: 'new gabs' },
|
||||||
|
no_recent_activity: { id: 'groups.sidebar-panel.item.no_recent_activity', defaultMessage: 'No recent activity' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => ({
|
||||||
|
groupIds: state.getIn(['group_lists', 'member']),
|
||||||
|
})
|
||||||
|
|
||||||
|
export default @connect(mapStateToProps)
|
||||||
|
@injectIntl
|
||||||
|
class GroupSidebarPanel extends ImmutablePureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
groupIds: ImmutablePropTypes.list,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { intl, groupIds } = this.props
|
||||||
|
const count = groupIds.count()
|
||||||
|
|
||||||
|
if (count === 0) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<PanelLayout
|
||||||
|
title={intl.formatMessage(messages.title)}
|
||||||
|
button={(
|
||||||
|
<NavLink
|
||||||
|
to='/groups/browse/member'
|
||||||
|
className={[styles.default, styles.fontWeightBold, styles.text, styles.colorBrand, styles.fontSize13PX, styles.noUnderline].join(' ')}
|
||||||
|
>
|
||||||
|
{intl.formatMessage(messages.all)}
|
||||||
|
</NavLink>
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className={styles.default}>
|
||||||
|
{
|
||||||
|
groupIds.slice(0, 6).map(groupId => (
|
||||||
|
<GroupPanelItem key={`group-panel-item-${groupId}`} id={groupId} />
|
||||||
|
))
|
||||||
|
}
|
||||||
|
{
|
||||||
|
count > 6 &&
|
||||||
|
<NavLink
|
||||||
|
to='/groups/browse/member'
|
||||||
|
className={[styles.default, styles.noUnderline, styles.paddingVertical5PX, styles.marginRightAuto, styles.marginTop5PX, styles.marginLeftAuto, styles.cursorPointer, styles.circle, styles.text, styles.displayFlex, styles.colorBrand].join(' ')}
|
||||||
|
>
|
||||||
|
{intl.formatMessage(messages.show_all)}
|
||||||
|
</NavLink>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</PanelLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps2 = (state, { id }) => ({
|
||||||
|
group: state.getIn(['groups', id]),
|
||||||
|
relationships: state.getIn(['group_relationships', id]),
|
||||||
|
})
|
||||||
|
|
||||||
|
@connect(mapStateToProps2)
|
||||||
|
@injectIntl
|
||||||
|
class GroupPanelItem extends ImmutablePureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
group: ImmutablePropTypes.map,
|
||||||
|
relationships: ImmutablePropTypes.map,
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
hovering: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseEnter = () => {
|
||||||
|
this.setState({ hovering: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseLeave = () => {
|
||||||
|
this.setState({ hovering: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { intl, group, relationships } = this.props
|
||||||
|
const { hovering } = this.state
|
||||||
|
|
||||||
|
if (!relationships) return null
|
||||||
|
|
||||||
|
const unreadCount = relationships.get('unread_count')
|
||||||
|
|
||||||
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
|
const titleClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
text: 1,
|
||||||
|
displayFlex: 1,
|
||||||
|
colorBrand: 1,
|
||||||
|
fontSize14PX: 1,
|
||||||
|
fontWeightBold: 1,
|
||||||
|
lineHeight15: 1,
|
||||||
|
underline: hovering,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavLink
|
||||||
|
to={`/groups/${group.get('id')}`}
|
||||||
|
className={[styles.default, styles.noUnderline, styles.marginTop5PX, styles.overflowHidden, styles.radiusSmall, styles.marginBottom10PX, styles.border1PX, styles.borderColorSubtle].join(' ')}
|
||||||
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
|
>
|
||||||
|
<div className={[styles.default, styles.height122PX].join(' ')}>
|
||||||
|
<img
|
||||||
|
src='https://gab.com/media/user/bz-5cf53d08403d4.jpeg'
|
||||||
|
alt={group.get('title')}
|
||||||
|
className={[styles.default, styles.objectFitCover, styles.height122PX, styles.width100PC].join(' ')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className={[styles.default, styles.paddingHorizontal10PX, styles.marginVertical5PX].join(' ')}>
|
||||||
|
<span className={titleClasses}>
|
||||||
|
{group.get('title')}
|
||||||
|
</span>
|
||||||
|
<span className={[styles.default, styles.text, styles.alignItemsCenter, styles.displayFlex, styles.flexRow, styles.colorSubtle, styles.fontSize13PX, styles.fontWeightNormal, styles.lineHeight15].join(' ')}>
|
||||||
|
{
|
||||||
|
unreadCount > 0 &&
|
||||||
|
<Fragment>
|
||||||
|
{shortNumberFormat(unreadCount)}
|
||||||
|
|
||||||
|
{intl.formatMessage(messages.new_statuses)}
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
{
|
||||||
|
unreadCount === 0 &&
|
||||||
|
<Fragment>
|
||||||
|
{intl.formatMessage(messages.no_recent_activity)}
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
<Icon className={styles.marginLeftAuto} width='10px' height='10px' />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</NavLink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,28 +1,32 @@
|
||||||
import classNames from 'classnames/bind'
|
import classNames from 'classnames/bind'
|
||||||
import Icon from '../icon'
|
|
||||||
|
|
||||||
export default class PanelLayout extends PureComponent {
|
export default class PanelLayout extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
subtitle: PropTypes.string,
|
subtitle: PropTypes.string,
|
||||||
icon: PropTypes.string,
|
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
hasBackground: PropTypes.boolean,
|
hasBackground: PropTypes.boolean,
|
||||||
|
button: PropTypes.node,
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { title, subtitle, icon, hasBackground, children } = this.props
|
const { title, subtitle, button, hasBackground, children } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<aside className={[styles.default, styles.backgroundSubtle, styles.overflowHidden, styles.radiusSmall, styles.marginBottom15PX].join(' ')}>
|
<aside className={[styles.default, styles.backgroundWhite, styles.overflowHidden, styles.radiusSmall, styles.marginBottom15PX, styles.borderColorSubtle, styles.border1PX].join(' ')}>
|
||||||
{
|
{
|
||||||
(title || subtitle) &&
|
(title || subtitle) &&
|
||||||
<div className={[styles.default, styles.paddingHorizontal15PX, styles.paddingVertical10PX, styles.borderColorSubtle, styles.borderBottom1PX].join(' ')}>
|
<div className={[styles.default, styles.paddingHorizontal15PX, styles.paddingVertical10PX, styles.borderColorSubtle, styles.borderBottom1PX].join(' ')}>
|
||||||
<div className={[styles.default, styles.flexRow, styles.alignItemsCenter].join(' ')}>
|
<div className={[styles.default, styles.flexRow, styles.alignItemsCenter].join(' ')}>
|
||||||
{icon && <Icon id={icon} height='16px' width='16px' className={[styles.default, styles.marginRight10PX].join(' ')} />}
|
<h1 className={[styles.default, styles.text, styles.fontWeightBold, styles.colorBlack, styles.fontSize16PX].join(' ')}>{title}</h1>
|
||||||
<span className={[styles.default, styles.text, styles.fontWeightExtraBold, styles.colorBlack, styles.fontSize19PX].join(' ')}>{title}</span>
|
{
|
||||||
|
!!button &&
|
||||||
|
<div className={[styles.default, styles.marginLeftAuto].join(' ')}>
|
||||||
|
{button}
|
||||||
</div>
|
</div>
|
||||||
{subtitle && <span className={[styles.default, styles.text, styles.colorSubtle, styles.fontSize13PX, styles.marginTop5PX].join(' ')}>{subtitle}</span>}
|
}
|
||||||
|
</div>
|
||||||
|
{subtitle && <h2 className={[styles.default, styles.text, styles.colorSubtle, styles.fontSize13PX, styles.fontWeightBold, styles.marginTop5PX].join(' ')}>{subtitle}</h2>}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
<div className={[styles.default, styles.paddingHorizontal15PX, styles.paddingVertical10PX].join(' ')}>
|
<div className={[styles.default, styles.paddingHorizontal15PX, styles.paddingVertical10PX].join(' ')}>
|
||||||
|
|
|
@ -10,7 +10,6 @@ export default class ProgressPanel extends PureComponent {
|
||||||
<PanelLayout
|
<PanelLayout
|
||||||
title="Gab's Operational Expenses"
|
title="Gab's Operational Expenses"
|
||||||
subtitle="We are 100% funded by you"
|
subtitle="We are 100% funded by you"
|
||||||
icon="comments"
|
|
||||||
hasBackground
|
hasBackground
|
||||||
>
|
>
|
||||||
<ProgressBar progress={monthlyExpensesComplete}/>
|
<ProgressBar progress={monthlyExpensesComplete}/>
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
import { injectIntl, defineMessages } from 'react-intl'
|
|
||||||
import classNames from 'classnames/bind'
|
|
||||||
import { me } from '../../initial_state';
|
|
||||||
import Icon from '../icon'
|
|
||||||
import PanelLayout from './panel_layout'
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
pro: { id: 'promo.gab_pro', defaultMessage: 'Upgrade to GabPRO' },
|
|
||||||
donation: { id: 'promo.donation', defaultMessage: 'Make a Donation' },
|
|
||||||
store: { id: 'promo.store', defaultMessage: 'Store - Buy Merch' },
|
|
||||||
apps: { id: 'promo.gab_apps', defaultMessage: 'Gab Apps' },
|
|
||||||
})
|
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
|
||||||
return {
|
|
||||||
isPro: state.getIn(['accounts', me, 'is_pro']),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default
|
|
||||||
@injectIntl
|
|
||||||
@connect(mapStateToProps)
|
|
||||||
class PromoPanel extends PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
isPro: PropTypes.bool,
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { isPro, intl } = this.props
|
|
||||||
|
|
||||||
const cx = classNames.bind(styles)
|
|
||||||
|
|
||||||
const items = [
|
|
||||||
{
|
|
||||||
text: intl.formatMessage(messages.pro),
|
|
||||||
href: 'https://pro.gab.com',
|
|
||||||
icon: 'arrow-up',
|
|
||||||
conditions: isPro,
|
|
||||||
highlighted: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: intl.formatMessage(messages.donation),
|
|
||||||
href: 'https://shop.dissenter.com/category/donations',
|
|
||||||
icon: 'heart',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: intl.formatMessage(messages.store),
|
|
||||||
href: 'https://shop.dissenter.com',
|
|
||||||
icon: 'shopping-cart',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: intl.formatMessage(messages.apps),
|
|
||||||
href: 'https://apps.gab.com',
|
|
||||||
icon: 'th',
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
return (
|
|
||||||
<PanelLayout>
|
|
||||||
{
|
|
||||||
items.map((item, i) => {
|
|
||||||
if (item.conditions === false) return null
|
|
||||||
|
|
||||||
const classes = cx({
|
|
||||||
default: true,
|
|
||||||
borderColorSubtle: i !== items.length - 1,
|
|
||||||
borderBottom1PX: i !== items.length - 1,
|
|
||||||
})
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div key={`promo-panel-item-${i}`} className={classes}>
|
|
||||||
<a className={[styles.default, styles.text, styles.colorBlack, styles.noUnderline, styles.paddingVertical10PX, styles.alignItemsCenter].join(' ')} href={item.href}>
|
|
||||||
<Icon id={item.icon} height='13px' width='13px' className={[styles.flex, styles.marginRight10PX].join(' ')} />
|
|
||||||
{item.text}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</PanelLayout>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,7 +6,7 @@ import TrendingItem from '../../components/trending_item';
|
||||||
import PanelLayout from './panel_layout';
|
import PanelLayout from './panel_layout';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
title: { id:'trends.title', defaultMessage: 'Trends' },
|
title: { id:'trends.title', defaultMessage: 'Trends for you' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
|
@ -36,16 +36,22 @@ class TrendsPanel extends ImmutablePureComponent {
|
||||||
render() {
|
render() {
|
||||||
const { intl, trends } = this.props;
|
const { intl, trends } = this.props;
|
||||||
|
|
||||||
if (trends.isEmpty()) {
|
// !!! TESTING !!!
|
||||||
return null;
|
// if (trends.isEmpty()) {
|
||||||
}
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelLayout id='hashtag' title={intl.formatMessage(messages.title)}>
|
<PanelLayout title={intl.formatMessage(messages.title)}>
|
||||||
<div className='panel__list'>
|
<div className={styles.default}>
|
||||||
{trends && trends.map(hashtag => (
|
{ /* trends && trends.map(hashtag => (
|
||||||
<TrendingItem key={hashtag.get('name')} hashtag={hashtag} />
|
<TrendingItem key={hashtag.get('name')} hashtag={hashtag} />
|
||||||
))}
|
)) */ }
|
||||||
|
<TrendingItem />
|
||||||
|
<TrendingItem />
|
||||||
|
<TrendingItem />
|
||||||
|
<TrendingItem />
|
||||||
|
<TrendingItem />
|
||||||
</div>
|
</div>
|
||||||
</PanelLayout>
|
</PanelLayout>
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,7 +7,7 @@ import PanelLayout from './panel_layout';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' },
|
dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' },
|
||||||
title: { id: 'who_to_follow.title', defaultMessage: 'Who To Follow' },
|
title: { id: 'who_to_follow.title', defaultMessage: 'Who to Follow' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
|
@ -37,15 +37,20 @@ class WhoToFollowPanel extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { intl, suggestions, dismissSuggestion } = this.props;
|
const { intl, /* suggestions, */ dismissSuggestion } = this.props;
|
||||||
|
// : testing!!! :
|
||||||
if (suggestions.isEmpty()) {
|
const suggestions = [
|
||||||
return null;
|
"1",
|
||||||
}
|
"1",
|
||||||
|
"1",
|
||||||
|
]
|
||||||
|
// if (suggestions.isEmpty()) {
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelLayout icon='users' title={intl.formatMessage(messages.title)}>
|
<PanelLayout title={intl.formatMessage(messages.title)}>
|
||||||
<div className='panel__list'>
|
<div className={styles.default}>
|
||||||
{suggestions && suggestions.map(accountId => (
|
{suggestions && suggestions.map(accountId => (
|
||||||
<AccountContainer
|
<AccountContainer
|
||||||
key={accountId}
|
key={accountId}
|
||||||
|
|
|
@ -10,8 +10,6 @@ import emojify from '../emoji/emoji';
|
||||||
import RelativeTimestamp from '../relative_timestamp';
|
import RelativeTimestamp from '../relative_timestamp';
|
||||||
import Button from '../button';
|
import Button from '../button';
|
||||||
|
|
||||||
import './poll.scss';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { pollId }) => ({
|
const mapStateToProps = (state, { pollId }) => ({
|
||||||
poll: state.getIn(['polls', pollId]),
|
poll: state.getIn(['polls', pollId]),
|
||||||
});
|
});
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './progress_bar';
|
|
|
@ -5,8 +5,6 @@ import IntersectionObserverWrapper from '../../features/ui/util/intersection_obs
|
||||||
import ColumnIndicator from '../column_indicator';
|
import ColumnIndicator from '../column_indicator';
|
||||||
import LoadMore from '../load_more';
|
import LoadMore from '../load_more';
|
||||||
|
|
||||||
import './scrollable_list.scss';
|
|
||||||
|
|
||||||
const MOUSE_IDLE_DELAY = 300;
|
const MOUSE_IDLE_DELAY = 300;
|
||||||
|
|
||||||
export default class ScrollableList extends PureComponent {
|
export default class ScrollableList extends PureComponent {
|
||||||
|
|
|
@ -3,8 +3,6 @@ import Overlay from 'react-overlays/lib/Overlay';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
import SearchPopout from '../search_popout';
|
import SearchPopout from '../search_popout';
|
||||||
|
|
||||||
import './search.scss';
|
|
||||||
|
|
||||||
export default class Search extends PureComponent {
|
export default class Search extends PureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
|
@ -17,7 +15,6 @@ export default class Search extends PureComponent {
|
||||||
onShow: PropTypes.func.isRequired,
|
onShow: PropTypes.func.isRequired,
|
||||||
openInRoute: PropTypes.bool,
|
openInRoute: PropTypes.bool,
|
||||||
placeholder: PropTypes.string.isRequired,
|
placeholder: PropTypes.string.isRequired,
|
||||||
className: PropTypes.string,
|
|
||||||
searchTitle: PropTypes.string,
|
searchTitle: PropTypes.string,
|
||||||
onChange: PropTypes.func.isRequired,
|
onChange: PropTypes.func.isRequired,
|
||||||
onKeyUp: PropTypes.func.isRequired,
|
onKeyUp: PropTypes.func.isRequired,
|
||||||
|
@ -40,32 +37,29 @@ export default class Search extends PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { value, submitted, placeholder, className, searchTitle, onKeyUp, handleClear, handleSubmit, withOverlay, onChange } = this.props;
|
const { value, submitted, placeholder, searchTitle, onKeyUp, handleClear, handleSubmit, withOverlay, onChange } = this.props;
|
||||||
const { expanded } = this.state;
|
const { expanded } = this.state;
|
||||||
|
|
||||||
const hasValue = value.length > 0 || submitted;
|
const hasValue = value ? value.length > 0 || submitted : 0;
|
||||||
const classes = classNames('search', className);
|
|
||||||
const iconClass = hasValue ? 'active' : '';
|
const iconClass = hasValue ? 'active' : '';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes}>
|
<div className={[styles.default, styles.backgroundColorSubtle3, styles.positionSticky, styles.justifyContentCenter, styles.top0, styles.z2, styles.height53PX, styles.marginBottom10PX].join(' ')}>
|
||||||
<label>
|
<div className={[styles.default, styles.backgroundSubtle2, styles.flexRow, styles.circle, styles.alignItemsCenter].join(' ')}>
|
||||||
<span className='invisible'>{placeholder}</span>
|
<Icon id='search' width='18px' height='18px' className={[styles.default, styles.marginLeft15PX, styles.marginRight10PX].join(' ')} />
|
||||||
<input
|
<input
|
||||||
className='search__input'
|
className={[styles.default, styles.text, styles.lineHeight125, styles.displayBlock, styles.paddingVertical10PX, styles.paddingHorizontal10PX, styles.backgroundTransparent, styles.fontSize15PX, styles.flexGrow1].join(' ')}
|
||||||
type='text'
|
type='text'
|
||||||
placeholder={placeholder}
|
placeholder='Search on Gab...'
|
||||||
value={value}
|
value={value}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
onKeyUp={onKeyUp}
|
onKeyUp={onKeyUp}
|
||||||
onFocus={this.handleFocus}
|
onFocus={this.handleFocus}
|
||||||
onBlur={this.handleBlur}
|
onBlur={this.handleBlur}
|
||||||
/>
|
/>
|
||||||
</label>
|
<div role='button' tabIndex='0' className={[styles.default, styles.paddingHorizontal10PX].join(' ')} onClick={handleClear}>
|
||||||
|
<Icon id='times-circle' width='18px' height='18px' className={iconClass} aria-label={placeholder} />
|
||||||
<div role='button' tabIndex='0' className='search__icon' onClick={handleClear}>
|
</div>
|
||||||
<Icon id='search' className={iconClass} />
|
|
||||||
<Icon id='times-circle' className={iconClass} aria-label={placeholder} />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -3,8 +3,6 @@ import spring from 'react-motion/lib/spring';
|
||||||
import Motion from '../../features/ui/util/optional_motion';
|
import Motion from '../../features/ui/util/optional_motion';
|
||||||
import { searchEnabled } from '../../initial_state';
|
import { searchEnabled } from '../../initial_state';
|
||||||
|
|
||||||
import './search_popout.scss';
|
|
||||||
|
|
||||||
export default class SearchPopout extends PureComponent {
|
export default class SearchPopout extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -2,7 +2,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import ToggleSwitch from '../toggle_switch';
|
import ToggleSwitch from '../toggle_switch';
|
||||||
|
|
||||||
import './setting_toggle.scss';
|
|
||||||
|
|
||||||
export default class SettingToggle extends ImmutablePureComponent {
|
export default class SettingToggle extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
|
import { Fragment } from 'react'
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { injectIntl, FormattedMessage } from 'react-intl';
|
import { injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
@ -18,8 +18,6 @@ import StatusActionBar from '../status_action_bar';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
import Poll from '../poll';
|
import Poll from '../poll';
|
||||||
|
|
||||||
import './status.scss';
|
|
||||||
|
|
||||||
// We use the component (and not the container) since we do not want
|
// We use the component (and not the container) since we do not want
|
||||||
// to use the progress bar to show download progress
|
// to use the progress bar to show download progress
|
||||||
import Bundle from '../../features/ui/util/bundle';
|
import Bundle from '../../features/ui/util/bundle';
|
||||||
|
@ -93,6 +91,7 @@ class Status extends ImmutablePureComponent {
|
||||||
group: ImmutablePropTypes.map,
|
group: ImmutablePropTypes.map,
|
||||||
promoted: PropTypes.bool,
|
promoted: PropTypes.bool,
|
||||||
onOpenProUpgradeModal: PropTypes.func,
|
onOpenProUpgradeModal: PropTypes.func,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Avoid checking props that are functions (and whose equality will always
|
// Avoid checking props that are functions (and whose equality will always
|
||||||
|
@ -403,7 +402,7 @@ class Status extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account === undefined || account === null) {
|
if (account === undefined || account === null) {
|
||||||
statusAvatar = <Avatar account={status.get('account')} size={42} />;
|
statusAvatar = <Avatar account={status.get('account')} size={50} />;
|
||||||
} else {
|
} else {
|
||||||
statusAvatar = <AvatarOverlay account={status.get('account')} friend={account} />;
|
statusAvatar = <AvatarOverlay account={status.get('account')} friend={account} />;
|
||||||
}
|
}
|
||||||
|
@ -428,16 +427,13 @@ class Status extends ImmutablePureComponent {
|
||||||
return (
|
return (
|
||||||
<HotKeys handlers={handlers}>
|
<HotKeys handlers={handlers}>
|
||||||
<div
|
<div
|
||||||
className={classNames('status__wrapper', `status__wrapper-${status.get('visibility')}`, {
|
className={[styles.default, styles.backgroundWhite, styles.radiusSmall, styles.marginBottom15PX, styles.border1PX, styles.borderColorSubtle].join(' ')}
|
||||||
'status__wrapper-reply': !!status.get('in_reply_to_id'),
|
|
||||||
read: unread === false,
|
|
||||||
focusable: !this.props.muted,
|
|
||||||
})}
|
|
||||||
tabIndex={this.props.muted ? null : 0}
|
tabIndex={this.props.muted ? null : 0}
|
||||||
data-featured={featured ? 'true' : null}
|
data-featured={featured ? 'true' : null}
|
||||||
aria-label={textForScreenReader(intl, status, rebloggedByText)}
|
aria-label={textForScreenReader(intl, status, rebloggedByText)}
|
||||||
ref={this.handleRef}
|
ref={this.handleRef}
|
||||||
>
|
>
|
||||||
|
|
||||||
{prepend}
|
{prepend}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
|
@ -448,33 +444,63 @@ class Status extends ImmutablePureComponent {
|
||||||
})}
|
})}
|
||||||
data-id={status.get('id')}
|
data-id={status.get('id')}
|
||||||
>
|
>
|
||||||
<div className='status__info'>
|
|
||||||
<div className='status__info__actions'>
|
<div className={[styles.default, styles.paddingHorizontal15PX, styles.paddingVertical10PX].join(' ')}>
|
||||||
<NavLink className='status__display-name' to={`/${status.getIn(['account', 'acct'])}`} title={status.getIn(['account', 'acct'])}>
|
<div className={[styles.default, styles.flexRow, styles.marginTop5PX].join(' ')}>
|
||||||
<div className='status__avatar'>{statusAvatar}</div>
|
<div className={[styles.default, styles.marginRight10PX].join(' ')}>{statusAvatar}</div>
|
||||||
|
<div className={[styles.default, styles.alignItemsStart, styles.flexGrow1, styles.marginTop5PX].join(' ')}>
|
||||||
|
<div className={[styles.default, styles.flexRow, styles.width100PC, styles.alignItemsStart].join(' ')}>
|
||||||
|
<NavLink
|
||||||
|
className={[styles.default, styles.flexRow, styles.alignItemsStart, styles.noUnderline].join(' ')}
|
||||||
|
to={`/${status.getIn(['account', 'acct'])}`}
|
||||||
|
title={status.getIn(['account', 'acct'])}
|
||||||
|
>
|
||||||
<DisplayName account={status.get('account')} />
|
<DisplayName account={status.get('account')} />
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<Icon id='ellipsis-h' className='status__info__actions__icon'/>
|
<Icon id='ellipsis-h' width='14px' height='15px' className={[styles.default, styles.marginLeftAuto].join(' ')} />
|
||||||
</div>
|
</div>
|
||||||
<div className='status__info__attributes'>
|
<div className={[styles.default, styles.flexRow, styles.alignItemsCenter, styles.lineHeight15].join(' ')}>
|
||||||
<NavLink to={statusUrl} className='status__relative-time'>
|
<NavLink
|
||||||
|
to={statusUrl}
|
||||||
|
className={[styles.default, styles.text, styles.fontSize13PX, styles.noUnderline, styles.colorSubtle].join(' ')}
|
||||||
|
>
|
||||||
<RelativeTimestamp timestamp={status.get('created_at')} />
|
<RelativeTimestamp timestamp={status.get('created_at')} />
|
||||||
</NavLink>
|
</NavLink>
|
||||||
<span className='status__info__dot-seperator'>•</span>
|
<span className={[styles.default, styles.text, styles.fontSize13PX, styles.marginLeft5PX, styles.colorSubtle].join(' ')}>•</span>
|
||||||
{ /* <Icon id='globe' className='status__info__attributes__item'/> */ }
|
<Icon id='globe' width='12px' height='12px' className={[styles.default, styles.displayInline, styles.marginLeft5PX, styles.fillColorSubtle].join(' ')}/>
|
||||||
<span className='status__info__attributes__item status__info__attributes__item--link'>Memes Group</span>
|
|
||||||
<span className='status__info__dot-seperator'>•</span>
|
{
|
||||||
<span className='status__info__attributes__item'>Edited</span>
|
status.get('group') &&
|
||||||
|
<Fragment>
|
||||||
|
<span className={[styles.default, styles.text, styles.fontSize13PX, styles.marginLeft5PX, styles.colorSubtle].join(' ')}>•</span>
|
||||||
|
<NavLink
|
||||||
|
to={`/groups/${status.getIn(['group', 'id'])}`}
|
||||||
|
className={[styles.default, styles.text, styles.fontSize13PX, styles.marginLeft5PX, styles.colorBlack].join(' ')}
|
||||||
|
>
|
||||||
|
{status.getIn(['group', 'title'])}
|
||||||
|
</NavLink>
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
status.get('revised_at') !== null &&
|
||||||
|
<Fragment>
|
||||||
|
<span className={[styles.default, styles.text, styles.fontSize13PX, styles.marginLeft5PX, styles.colorSubtle].join(' ')}>•</span>
|
||||||
|
<button
|
||||||
|
onClick={() => other.onShowRevisions(status)}
|
||||||
|
className={[styles.default, styles.text, styles.fontSize13PX, styles.marginLeft5PX, styles.colorSubtle].join(' ')}
|
||||||
|
>
|
||||||
|
Edited
|
||||||
|
</button>
|
||||||
|
</Fragment>
|
||||||
|
}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{((!group && status.get('group')) || status.get('revised_at') !== null) && (
|
<div className={[styles.default, styles.paddingHorizontal15PX].join(' ')}>
|
||||||
<div className='status__meta'>
|
|
||||||
{!group && status.get('group') && <React.Fragment>Posted in <NavLink to={`/groups/${status.getIn(['group', 'id'])}`}>{status.getIn(['group', 'title'])}</NavLink></React.Fragment>}
|
|
||||||
{status.get('revised_at') !== null && <a onClick={() => other.onShowRevisions(status)}> Edited</a>}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<StatusContent
|
<StatusContent
|
||||||
status={status}
|
status={status}
|
||||||
reblogContent={reblogContent}
|
reblogContent={reblogContent}
|
||||||
|
@ -483,18 +509,19 @@ class Status extends ImmutablePureComponent {
|
||||||
onExpandedToggle={this.handleExpandedToggle}
|
onExpandedToggle={this.handleExpandedToggle}
|
||||||
collapsable
|
collapsable
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{media}
|
{ /* media */ }
|
||||||
|
|
||||||
{ /* status.get('quote') && <StatusQuote
|
{ /* status.get('quote') && <StatusQuote
|
||||||
id={status.get('quote')}
|
id={status.get('quote')}
|
||||||
/> */ }
|
/> */ }
|
||||||
|
|
||||||
{showThread && status.get('in_reply_to_id') && status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) && (
|
{ /* showThread && status.get('in_reply_to_id') && status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) && (
|
||||||
<button className='status__content__read-more-button' onClick={this.handleClick}>
|
<button className='status__content__read-more-button' onClick={this.handleClick}>
|
||||||
<FormattedMessage id='status.show_thread' defaultMessage='Show thread' />
|
<FormattedMessage id='status.show_thread' defaultMessage='Show thread' />
|
||||||
</button>
|
</button>
|
||||||
)}
|
) */ }
|
||||||
|
|
||||||
<StatusActionBar status={status} account={account} {...other} />
|
<StatusActionBar status={status} account={account} {...other} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
|
import classNames from 'classnames/bind'
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { openModal } from '../../actions/modal';
|
import { openModal } from '../../actions/modal';
|
||||||
import { me, isStaff } from '../../initial_state';
|
import { me, isStaff } from '../../initial_state';
|
||||||
import DropdownMenuContainer from '../../containers/dropdown_menu_container';
|
import DropdownMenuContainer from '../../containers/dropdown_menu_container';
|
||||||
import ComposeFormContainer from '../../features/compose/containers/compose_form_container';
|
import ComposeFormContainer from '../../features/compose/containers/compose_form_container';
|
||||||
import IconButton from '../icon_button';
|
import Icon from '../icon';
|
||||||
|
|
||||||
import './status_action_bar.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
||||||
|
@ -48,6 +46,77 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
class StatusActionBarItem extends PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
title: PropTypes.string.isRequired,
|
||||||
|
onClick: PropTypes.func.isRequired,
|
||||||
|
icon: PropTypes.string.isRequired,
|
||||||
|
active: PropTypes.bool,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
hovering: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseEnter = () => {
|
||||||
|
this.setState({ hovering: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseLeave = () => {
|
||||||
|
this.setState({ hovering: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { title, onClick, icon, active, disabled } = this.props
|
||||||
|
const { hovering } = this.state
|
||||||
|
|
||||||
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
|
const btnClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
text: 1,
|
||||||
|
fontSize15PX: 1,
|
||||||
|
cursorPointer: 1,
|
||||||
|
displayFlex: 1,
|
||||||
|
justifyContentCenter: 1,
|
||||||
|
flexRow: 1,
|
||||||
|
alignItemsCenter: 1,
|
||||||
|
paddingVertical10PX: 1,
|
||||||
|
paddingHorizontal10PX: 1,
|
||||||
|
width100PC: 1,
|
||||||
|
radiusSmall: 1,
|
||||||
|
backgroundTransparent: !hovering,
|
||||||
|
backgroundSubtle2: hovering,
|
||||||
|
colorBlack: !hovering,
|
||||||
|
colorBrand: hovering,
|
||||||
|
})
|
||||||
|
|
||||||
|
const iconClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
marginRight10PX: 1,
|
||||||
|
fillColorSubtle: !hovering,
|
||||||
|
fillColorBrand: hovering,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[styles.default, styles.flexGrow1, styles.paddingHorizontal10PX].join(' ')}>
|
||||||
|
<button
|
||||||
|
className={btnClasses}
|
||||||
|
onClick={onClick}
|
||||||
|
active={active}
|
||||||
|
disabled={disabled}
|
||||||
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
|
>
|
||||||
|
<Icon width='16px' height='16px' icon={icon} className={iconClasses} />
|
||||||
|
{title}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default @connect(null, mapDispatchToProps)
|
export default @connect(null, mapDispatchToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
class StatusActionBar extends ImmutablePureComponent {
|
class StatusActionBar extends ImmutablePureComponent {
|
||||||
|
@ -254,7 +323,6 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
|
|
||||||
const reblogCount = status.get('reblogs_count');
|
const reblogCount = status.get('reblogs_count');
|
||||||
const reblogTitle = !publicStatus ? formatMessage(messages.cannot_reblog) : formatMessage(messages.reblog);
|
const reblogTitle = !publicStatus ? formatMessage(messages.cannot_reblog) : formatMessage(messages.reblog);
|
||||||
const reblogIcon = (status.get('visibility') === 'private') ? 'lock' : 'retweet';
|
|
||||||
|
|
||||||
const favoriteCount = status.get('favourites_count');
|
const favoriteCount = status.get('favourites_count');
|
||||||
|
|
||||||
|
@ -264,55 +332,36 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
|
|
||||||
const menu = this._makeMenu(publicStatus);
|
const menu = this._makeMenu(publicStatus);
|
||||||
|
|
||||||
return (
|
const items = [
|
||||||
<div className='status-action-bar'>
|
{
|
||||||
<div className='status-action-bar__items'>
|
title: formatMessage(messages.favourite),
|
||||||
<div className='status-action-bar-item'>
|
icon: 'star',
|
||||||
<IconButton
|
active: status.get('favourited'),
|
||||||
className='status-action-bar-item__btn star-icon'
|
onClick: this.handleFavouriteClick,
|
||||||
animate
|
},
|
||||||
active={status.get('favourited')}
|
{
|
||||||
pressed={status.get('favourited')}
|
title: replyTitle,
|
||||||
title={formatMessage(messages.favourite)}
|
icon: 'reply',
|
||||||
icon='star'
|
active: 0,
|
||||||
onClick={this.handleFavouriteClick}
|
onClick: this.handleReplyClick,
|
||||||
text='Like'
|
},
|
||||||
/>
|
{
|
||||||
{ /* favoriteCount !== 0 && <span className='detailed-status__link'>{favoriteCount}</span> */ }
|
title: reblogTitle,
|
||||||
</div>
|
icon: (status.get('visibility') === 'private') ? 'lock' : 'retweet',
|
||||||
|
disabled: !publicStatus,
|
||||||
<div className='status-action-bar-item'>
|
active: status.get('reblogged'),
|
||||||
<IconButton
|
onClick: this.handleReblogClick,
|
||||||
className='status-action-bar-item__btn'
|
|
||||||
title={replyTitle}
|
|
||||||
icon={status.get('in_reply_to_account_id') === status.getIn(['account', 'id']) ? 'reply' : replyIcon}
|
|
||||||
onClick={this.handleReplyClick}
|
|
||||||
text='Comment'
|
|
||||||
/>
|
|
||||||
{ /*
|
|
||||||
replyCount !== 0 &&
|
|
||||||
<Link to={`/${status.getIn(['account', 'acct'])}/posts/${status.get('id')}`} className='status-action-bar-item__link'>{replyCount}</Link>
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
</div>
|
]
|
||||||
|
|
||||||
<div className='status-action-bar-item'>
|
return (
|
||||||
<IconButton
|
<div className={[styles.default, styles.marginTop10PX, styles.paddingHorizontal10PX].join(' ')}>
|
||||||
className='status-action-bar-item__btn'
|
<div className={[styles.default, styles.paddingVertical2PX, styles.flexRow, styles.borderTop1PX, styles.borderColorSubtle].join(' ')}>
|
||||||
disabled={!publicStatus}
|
{
|
||||||
active={status.get('reblogged')}
|
items.map((item, i) => (
|
||||||
pressed={status.get('reblogged')}
|
<StatusActionBarItem {...item} />
|
||||||
title={reblogTitle}
|
))
|
||||||
icon={reblogIcon}
|
}
|
||||||
onClick={this.handleReblogClick}
|
|
||||||
text='Share'
|
|
||||||
/>
|
|
||||||
{ /* reblogCount !== 0 && <Link to={`/${status.getIn(['account', 'acct'])}/posts/${status.get('id')}/reblogs`} className='status-action-bar-item__link'>{reblogCount}</Link> */ }
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/*<div className='status__action-bar__counter'>
|
|
||||||
<IconButton className='status__action-bar-button' disabled={!publicStatus} title={!publicStatus ? formatMessage(messages.cannot_quote) : formatMessage(messages.quote)} icon='quote-left' onClick={this.handleQuoteClick} />
|
|
||||||
</div>*/}
|
|
||||||
|
|
||||||
{/*<div className='status-action-bar__dropdown'>
|
{/*<div className='status-action-bar__dropdown'>
|
||||||
<DropdownMenuContainer
|
<DropdownMenuContainer
|
||||||
|
|
|
@ -8,8 +8,6 @@ import Bundle from '../../features/ui/util/bundle';
|
||||||
import StatusContent from '../status_content';
|
import StatusContent from '../status_content';
|
||||||
import ToggleSwitch from '../toggle_switch';
|
import ToggleSwitch from '../toggle_switch';
|
||||||
|
|
||||||
import './status_check_box.scss';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { id }) => ({
|
const mapStateToProps = (state, { id }) => ({
|
||||||
status: state.getIn(['statuses', id]),
|
status: state.getIn(['statuses', id]),
|
||||||
checked: state.getIn(['reports', 'new', 'status_ids'], ImmutableSet()).includes(id),
|
checked: state.getIn(['reports', 'new', 'status_ids'], ImmutableSet()).includes(id),
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
|
import { Fragment } from 'react';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { isRtl } from '../../utils/rtl';
|
import { isRtl } from '../../utils/rtl';
|
||||||
import Permalink from '../permalink/permalink';
|
import Permalink from '../permalink/permalink';
|
||||||
import Icon from '../icon';
|
import Icon from '../icon';
|
||||||
|
|
||||||
import './status_content.scss';
|
|
||||||
|
|
||||||
const MAX_HEIGHT = 200;
|
const MAX_HEIGHT = 200;
|
||||||
|
|
||||||
export default class StatusContent extends ImmutablePureComponent {
|
const messages = defineMessages({
|
||||||
|
showMore: { id: 'status.show_more', defaultMessage: 'Show more' },
|
||||||
|
showLess: { id: 'status.show_less', defaultMessage: 'Show less' },
|
||||||
|
})
|
||||||
|
|
||||||
|
export default
|
||||||
|
@injectIntl
|
||||||
|
class StatusContent extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
router: PropTypes.object,
|
||||||
|
@ -23,6 +29,7 @@ export default class StatusContent extends ImmutablePureComponent {
|
||||||
onExpandedToggle: PropTypes.func,
|
onExpandedToggle: PropTypes.func,
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
collapsable: PropTypes.bool,
|
collapsable: PropTypes.bool,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
|
@ -145,7 +152,7 @@ export default class StatusContent extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { status } = this.props;
|
const { status, intl } = this.props;
|
||||||
|
|
||||||
if (status.get('content').length === 0) return null;
|
if (status.get('content').length === 0) return null;
|
||||||
|
|
||||||
|
@ -164,12 +171,6 @@ export default class StatusContent extends ImmutablePureComponent {
|
||||||
directionStyle.direction = 'rtl';
|
directionStyle.direction = 'rtl';
|
||||||
}
|
}
|
||||||
|
|
||||||
const readMoreButton = (
|
|
||||||
<button className='status__content__read-more-button' onClick={this.props.onClick} key='read-more'>
|
|
||||||
<FormattedMessage id='status.read_more' defaultMessage='Read more' />
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (status.get('spoiler_text').length > 0) {
|
if (status.get('spoiler_text').length > 0) {
|
||||||
let mentionsPlaceholder = '';
|
let mentionsPlaceholder = '';
|
||||||
|
|
||||||
|
@ -179,7 +180,7 @@ export default class StatusContent extends ImmutablePureComponent {
|
||||||
</Permalink>
|
</Permalink>
|
||||||
)).reduce((aggregate, item) => [...aggregate, item, ' '], []);
|
)).reduce((aggregate, item) => [...aggregate, item, ' '], []);
|
||||||
|
|
||||||
const toggleText = hidden ? <FormattedMessage id='status.show_more' defaultMessage='Show more' /> : <FormattedMessage id='status.show_less' defaultMessage='Show less' />;
|
const toggleText = intl.formatMessaeg(hidden ? messages.showMore : messages.showLess);
|
||||||
|
|
||||||
if (hidden) {
|
if (hidden) {
|
||||||
mentionsPlaceholder = <div>{mentionLinks}</div>;
|
mentionsPlaceholder = <div>{mentionLinks}</div>;
|
||||||
|
@ -199,32 +200,37 @@ export default class StatusContent extends ImmutablePureComponent {
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (this.props.onClick) {
|
} else if (this.props.onClick) {
|
||||||
const output = [
|
return (
|
||||||
|
<Fragment>
|
||||||
<div
|
<div
|
||||||
ref={this.setRef}
|
ref={this.setRef}
|
||||||
tabIndex='0'
|
tabIndex='0'
|
||||||
key='content'
|
className={[styles.statusContent].join(' ')}
|
||||||
className={classNames}
|
|
||||||
style={directionStyle}
|
style={directionStyle}
|
||||||
dangerouslySetInnerHTML={content}
|
dangerouslySetInnerHTML={content}
|
||||||
lang={status.get('language')}
|
lang={status.get('language')}
|
||||||
onMouseDown={this.handleMouseDown}
|
onMouseDown={this.handleMouseDown}
|
||||||
onMouseUp={this.handleMouseUp}
|
onMouseUp={this.handleMouseUp}
|
||||||
/>,
|
/>
|
||||||
];
|
|
||||||
|
|
||||||
if (this.state.collapsed) {
|
{
|
||||||
output.push(readMoreButton);
|
this.state.collapsed &&
|
||||||
|
<button
|
||||||
|
className={[styles.default].join(' ')}
|
||||||
|
onClick={this.props.onClick}
|
||||||
|
>
|
||||||
|
<FormattedMessage id='status.read_more' defaultMessage='Read more' />
|
||||||
|
</button>
|
||||||
}
|
}
|
||||||
|
</Fragment>
|
||||||
return output;
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
tabIndex='0'
|
tabIndex='0'
|
||||||
ref={this.setRef}
|
ref={this.setRef}
|
||||||
className='status__content'
|
className={[styles.statusContent].join(' ')}
|
||||||
style={directionStyle}
|
style={directionStyle}
|
||||||
dangerouslySetInnerHTML={content}
|
dangerouslySetInnerHTML={content}
|
||||||
lang={status.get('language')}
|
lang={status.get('language')}
|
||||||
|
|
|
@ -3,8 +3,6 @@ import StatusContent from '../status_content';
|
||||||
import DisplayName from '../display_name';
|
import DisplayName from '../display_name';
|
||||||
import { NavLink } from 'react-router-dom';
|
import { NavLink } from 'react-router-dom';
|
||||||
|
|
||||||
import './status_quote.scss';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, { id }) => ({
|
const mapStateToProps = (state, { id }) => ({
|
||||||
status: state.getIn(['statuses', id]),
|
status: state.getIn(['statuses', id]),
|
||||||
account: state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]),
|
account: state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]),
|
||||||
|
|
|
@ -4,8 +4,6 @@ import { me } from '../../initial_state';
|
||||||
import ComposeFormContainer from '../../features/compose/containers/compose_form_container';
|
import ComposeFormContainer from '../../features/compose/containers/compose_form_container';
|
||||||
import Avatar from '../avatar';
|
import Avatar from '../avatar';
|
||||||
|
|
||||||
import './timeline_compose_block.scss';
|
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
return {
|
return {
|
||||||
account: state.getIn(['accounts', me]),
|
account: state.getIn(['accounts', me]),
|
||||||
|
@ -28,9 +26,9 @@ class TimelineComposeBlock extends ImmutablePureComponent {
|
||||||
const { account, size, ...rest } = this.props;
|
const { account, size, ...rest } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='timeline-compose-block'>
|
<div className={[styles.default, styles.flexRow, styles.radiusSmall, styles.border1PX, styles.borderColorSubtle, styles.backgroundWhite, styles.marginBottom15PX, styles.paddingVertical10PX, styles.paddingHorizontal15PX].join(' ')}>
|
||||||
<div className='timeline-compose-block__avatar'>
|
<div className={[styles.default, styles.marginRight10PX].join(' ')}>
|
||||||
<Avatar account={account} size={size} />
|
<Avatar account={account} size={46} />
|
||||||
</div>
|
</div>
|
||||||
<ComposeFormContainer {...rest} />
|
<ComposeFormContainer {...rest} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,8 +2,6 @@ import { FormattedMessage } from 'react-intl';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { shortNumberFormat } from '../../utils/numbers';
|
import { shortNumberFormat } from '../../utils/numbers';
|
||||||
|
|
||||||
import './timeline_queue_button_header.scss';
|
|
||||||
|
|
||||||
export default class TimelineQueueButtonHeader extends PureComponent {
|
export default class TimelineQueueButtonHeader extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import Toggle from 'react-toggle';
|
import Toggle from 'react-toggle';
|
||||||
|
|
||||||
import './toggle_switch.scss';
|
|
||||||
|
|
||||||
export default class ToggleSwitch extends PureComponent {
|
export default class ToggleSwitch extends PureComponent {
|
||||||
render() {
|
render() {
|
||||||
return <Toggle {...this.props} />
|
return <Toggle {...this.props} />
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import { FormattedMessage } from 'react-intl'
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import { NavLink } from 'react-router-dom'
|
||||||
|
import classNames from 'classnames/bind'
|
||||||
|
import { shortNumberFormat } from '../utils/numbers'
|
||||||
|
|
||||||
|
export default class TrendingItem extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
hashtag: ImmutablePropTypes.map.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
state = {
|
||||||
|
hovering: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseEnter = () => {
|
||||||
|
this.setState({ hovering: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseLeave = () => {
|
||||||
|
this.setState({ hovering: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { hashtag } = this.props
|
||||||
|
const { hovering } = this.state
|
||||||
|
|
||||||
|
const cx = classNames.bind(styles)
|
||||||
|
const subtitleClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
text: 1,
|
||||||
|
displayFlex: 1,
|
||||||
|
fontSize13PX: 1,
|
||||||
|
fontWeightNormal: 1,
|
||||||
|
colorSubtle: 1,
|
||||||
|
underline: hovering,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavLink
|
||||||
|
to='/test'
|
||||||
|
className={[styles.default, styles.noUnderline, styles.marginBottom10PX].join(' ')}
|
||||||
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
|
>
|
||||||
|
<span className={[styles.default, styles.text, styles.displayFlex, styles.colorBrand, styles.fontSize15PX, styles.fontWeightBold, styles.lineHeight15].join(' ')}>#randomhashtag</span>
|
||||||
|
<span className={subtitleClasses}>10,240 Gabs</span>
|
||||||
|
</NavLink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './trending_item';
|
|
|
@ -1,49 +0,0 @@
|
||||||
import { Sparklines, SparklinesCurve } from 'react-sparklines';
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
|
||||||
import { shortNumberFormat } from '../../utils/numbers';
|
|
||||||
import Permalink from '../permalink';
|
|
||||||
|
|
||||||
import './trending_item.scss';
|
|
||||||
|
|
||||||
export default class TrendingItem extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
hashtag: ImmutablePropTypes.map.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { hashtag } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='trending-item'>
|
|
||||||
<div className='trending-item__text'>
|
|
||||||
<Permalink href={hashtag.get('url')} to={`/tags/${hashtag.get('name')}`}>
|
|
||||||
#<span>{hashtag.get('name')}</span>
|
|
||||||
</Permalink>
|
|
||||||
|
|
||||||
<FormattedMessage
|
|
||||||
id='trends.count_by_accounts'
|
|
||||||
defaultMessage='{count} {rawCount, plural, one {person} other {people}} talking'
|
|
||||||
values={{
|
|
||||||
rawCount: hashtag.getIn(['history', 0, 'accounts']),
|
|
||||||
count: <strong>{shortNumberFormat(hashtag.getIn(['history', 0, 'accounts']))}</strong>,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='trending-item__uses'>
|
|
||||||
{shortNumberFormat(hashtag.getIn(['history', 0, 'uses']))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='trending-item__sparkline'>
|
|
||||||
<Sparklines width={50} height={28} data={hashtag.get('history').reverse().map(day => day.get('uses')).toArray()}>
|
|
||||||
<SparklinesCurve style={{ fill: 'none' }} />
|
|
||||||
</Sparklines>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,55 +0,0 @@
|
||||||
.trending-item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 15px;
|
|
||||||
border-bottom: 1px solid lighten($ui-base-color, 8%);
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__name {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
color: $dark-text-color;
|
|
||||||
|
|
||||||
@include text-overflow(nowrap);
|
|
||||||
|
|
||||||
strong {
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
display: block;
|
|
||||||
color: $darker-text-color;
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
@include text-sizing(14px, 500);
|
|
||||||
@include text-overflow(nowrap);
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus,
|
|
||||||
&:active {
|
|
||||||
span {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__uses {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
width: 100px;
|
|
||||||
color: $secondary-text-color;
|
|
||||||
|
|
||||||
@include text-sizing(24px, 500, 36px, center);
|
|
||||||
}
|
|
||||||
|
|
||||||
&__sparkline {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
width: 50px;
|
|
||||||
|
|
||||||
path {
|
|
||||||
stroke: lighten($highlight-text-color, 6%) !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -2,8 +2,6 @@ import { FormattedMessage } from 'react-intl';
|
||||||
import spring from 'react-motion/lib/spring';
|
import spring from 'react-motion/lib/spring';
|
||||||
import Motion from '../../features/ui/util/optional_motion';
|
import Motion from '../../features/ui/util/optional_motion';
|
||||||
|
|
||||||
import './upload_area.scss';
|
|
||||||
|
|
||||||
export default class UploadArea extends PureComponent {
|
export default class UploadArea extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
import { NavLink } from 'react-router-dom'
|
||||||
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import classNames from 'classnames/bind'
|
||||||
|
import { autoPlayGif, me } from '../initial_state'
|
||||||
|
import { makeGetAccount } from '../selectors'
|
||||||
|
import { shortNumberFormat } from '../utils/numbers'
|
||||||
|
import Avatar from './avatar'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
gabs: { id: 'account.posts', defaultMessage: 'Gabs' },
|
||||||
|
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
||||||
|
follows: { id: 'account.follows', defaultMessage: 'Follows' }
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
const getAccount = makeGetAccount()
|
||||||
|
|
||||||
|
return {
|
||||||
|
account: getAccount(state, me),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default @connect(mapStateToProps)
|
||||||
|
@injectIntl
|
||||||
|
class UserPanel extends ImmutablePureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
account: ImmutablePropTypes.map,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { account, intl } = this.props
|
||||||
|
const displayNameHtml = { __html: account.get('display_name_html') }
|
||||||
|
|
||||||
|
const statItems = [
|
||||||
|
{
|
||||||
|
to: `/${account.get('acct')}`,
|
||||||
|
title: intl.formatMessage(messages.gabs),
|
||||||
|
value: shortNumberFormat(account.get('statuses_count')),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
to: `/${account.get('acct')}/followers`,
|
||||||
|
title: intl.formatMessage(messages.followers),
|
||||||
|
value: shortNumberFormat(account.get('followers_count')),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
to: `/${account.get('acct')}/following`,
|
||||||
|
title: intl.formatMessage(messages.follows),
|
||||||
|
value: shortNumberFormat(account.get('following_count')),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
return (
|
||||||
|
<aside className={[styles.default, styles.backgroundWhite, styles.overflowHidden, styles.radiusSmall, styles.marginBottom15PX, styles.borderColorSubtle, styles.border1PX].join(' ')}>
|
||||||
|
<div className={[styles.default].join(' ')}>
|
||||||
|
|
||||||
|
<div className={[styles.default, styles.height122PX].join(' ')}>
|
||||||
|
<img
|
||||||
|
className={[styles.default, styles.image, styles.height122PX, styles.width100PC, styles.objectFitCover].join(' ')}
|
||||||
|
src={autoPlayGif ? account.get('header') : account.get('header_static')}
|
||||||
|
alt=''
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={[styles.default, styles.positionRelative].join(' ')}>
|
||||||
|
<NavLink
|
||||||
|
className={[styles.default, styles.flexRow, styles.paddingVertical10PX, styles.paddingHorizontal15PX, styles.noUnderline].join(' ')}
|
||||||
|
to={`/${account.get('acct')}`}
|
||||||
|
>
|
||||||
|
<div className={[styles.default, styles.marginTopNeg30PX, styles.circle, styles.borderColorWhite, styles.border2PX].join(' ')}>
|
||||||
|
<Avatar account={account} size={62} />
|
||||||
|
</div>
|
||||||
|
<h1 className={[styles.default, styles.marginLeft15PX].join(' ')}>
|
||||||
|
<span
|
||||||
|
className={[styles.default, styles.text, styles.displayBlock, styles.textOverflowEllipsis, styles.fontSize14PX, styles.colorBlack, styles.fontWeightBold].join(' ')}
|
||||||
|
dangerouslySetInnerHTML={displayNameHtml}
|
||||||
|
/>
|
||||||
|
<small className={[styles.default, styles.text, styles.displayBlock, styles.textOverflowEllipsis, styles.fontWeightNormal, styles.fontSize14PX, styles.colorSubtle].join(' ')}>@{account.get('acct')}</small>
|
||||||
|
</h1>
|
||||||
|
</NavLink>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={[styles.default, styles.marginBottom15PX, styles.marginTop5PX, styles.flexRow, styles.paddingHorizontal15PX].join(' ')}>
|
||||||
|
{
|
||||||
|
statItems.map((statItem, i) => (
|
||||||
|
<UserPanelStatItem {...statItem} key={`user-panel-stat-item-${i}`} />
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class UserPanelStatItem extends PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
to: PropTypes.string,
|
||||||
|
title: PropTypes.string,
|
||||||
|
value: PropTypes.string,
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
hovering: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseEnter = () => {
|
||||||
|
this.setState({ hovering: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseLeave = () => {
|
||||||
|
this.setState({ hovering: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { to, title, value } = this.props
|
||||||
|
const { hovering } = this.state
|
||||||
|
|
||||||
|
const cx = classNames.bind(styles)
|
||||||
|
const titleClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
fontWeightNormal: 1,
|
||||||
|
text: 1,
|
||||||
|
displayFlex: 1,
|
||||||
|
fontSize13PX: 1,
|
||||||
|
colorSubtle: !hovering,
|
||||||
|
colorBlack: hovering,
|
||||||
|
underline: hovering,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NavLink
|
||||||
|
to={to}
|
||||||
|
title={`${value} ${title}`}
|
||||||
|
className={[styles.default, styles.flexGrow1, styles.cursorPointer, styles.noUnderline, styles.paddingRight15PX].join(' ')}
|
||||||
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={[styles.default, styles.fontWeightBold, styles.text, styles.displayFlex, styles.fontSize19PX, styles.colorBrand].join(' ')}
|
||||||
|
>
|
||||||
|
{value}
|
||||||
|
</span>
|
||||||
|
<strong
|
||||||
|
className={titleClasses}
|
||||||
|
>
|
||||||
|
{title}
|
||||||
|
</strong>
|
||||||
|
</NavLink>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './user_panel';
|
|
|
@ -1,95 +0,0 @@
|
||||||
import { Link } from 'react-router-dom';
|
|
||||||
import { injectIntl, defineMessages } from 'react-intl';
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
|
||||||
import { autoPlayGif, me } from '../../initial_state';
|
|
||||||
import { makeGetAccount } from '../../selectors';
|
|
||||||
import { shortNumberFormat } from '../../utils/numbers';
|
|
||||||
import Avatar from '../avatar';
|
|
||||||
|
|
||||||
import './user_panel.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
|
||||||
gabs: { id:'account.posts', defaultMessage: 'Gabs' },
|
|
||||||
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
|
||||||
follows: { id: 'account.follows', defaultMessage: 'Follows' }
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
|
||||||
const getAccount = makeGetAccount();
|
|
||||||
|
|
||||||
return {
|
|
||||||
account: getAccount(state, me),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default @connect(mapStateToProps)
|
|
||||||
@injectIntl
|
|
||||||
class UserPanel extends ImmutablePureComponent {
|
|
||||||
static propTypes = {
|
|
||||||
account: ImmutablePropTypes.map,
|
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { account, intl } = this.props;
|
|
||||||
const displayNameHtml = { __html: account.get('display_name_html') };
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='user-panel'>
|
|
||||||
<div className='user-panel__container'>
|
|
||||||
|
|
||||||
<div className='user-panel__header'>
|
|
||||||
<img src={autoPlayGif ? account.get('header') : account.get('header_static')} alt='' />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='user-panel__profile'>
|
|
||||||
<Link to={`/${account.get('acct')}`} title={account.get('acct')}>
|
|
||||||
<Avatar account={account} />
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='user-panel__meta'>
|
|
||||||
|
|
||||||
<div className='user-panel__account'>
|
|
||||||
<h1>
|
|
||||||
<Link to={`/${account.get('acct')}`}>
|
|
||||||
<span className='user-panel__account__name' dangerouslySetInnerHTML={displayNameHtml} />
|
|
||||||
<small className='user-panel__account__username'>@{account.get('acct')}</small>
|
|
||||||
</Link>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='user-panel__stats-block'>
|
|
||||||
|
|
||||||
<div className='user-panel-stats-item'>
|
|
||||||
<Link to={`/${account.get('acct')}`} title={intl.formatNumber(account.get('statuses_count'))}>
|
|
||||||
<strong className='user-panel-stats-item__value'>{shortNumberFormat(account.get('statuses_count'))}</strong>
|
|
||||||
<span className='user-panel-stats-item__label'>{intl.formatMessage(messages.gabs)}</span>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='user-panel-stats-item'>
|
|
||||||
<Link to={`/${account.get('acct')}/followers`} title={intl.formatNumber(account.get('followers_count'))}>
|
|
||||||
<strong className='user-panel-stats-item__value'>{shortNumberFormat(account.get('followers_count'))}</strong>
|
|
||||||
<span className='user-panel-stats-item__label'>{intl.formatMessage(messages.followers)}</span>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='user-panel-stats-item'>
|
|
||||||
<Link to={`/${account.get('acct')}/following`} title={intl.formatNumber(account.get('following_count'))}>
|
|
||||||
<strong className='user-panel-stats-item__value'>{shortNumberFormat(account.get('following_count'))}</strong>
|
|
||||||
<span className='user-panel-stats-item__label'>{intl.formatMessage(messages.follows)}</span>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,125 +0,0 @@
|
||||||
.user-panel {
|
|
||||||
display: flex;
|
|
||||||
width: 265px;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow-y: hidden;
|
|
||||||
|
|
||||||
// @include gab-container-standards();
|
|
||||||
|
|
||||||
&__header {
|
|
||||||
display: block;
|
|
||||||
background: lighten($gab-background-container, 4%);
|
|
||||||
|
|
||||||
@include size(100%, 112px);
|
|
||||||
|
|
||||||
body.theme-gabsocial-light & {
|
|
||||||
background: darken($gab-background-container-light, 4%);
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
display: block;
|
|
||||||
margin: 0;
|
|
||||||
object-fit: cover;
|
|
||||||
|
|
||||||
@include size(100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__profile {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
padding: 0 10px;
|
|
||||||
margin-top: -53px;
|
|
||||||
|
|
||||||
.account__avatar {
|
|
||||||
display: block;
|
|
||||||
border: 6px solid $gab-background-base;
|
|
||||||
background-size: cover;
|
|
||||||
|
|
||||||
@include size(82px);
|
|
||||||
|
|
||||||
body.theme-gabsocial-light & {
|
|
||||||
border: 6px solid $gab-background-base-light;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__meta {
|
|
||||||
display: block;
|
|
||||||
padding: 6px 20px 17px 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__account {
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: $primary-text-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__name {
|
|
||||||
display: block;
|
|
||||||
color: #fff;
|
|
||||||
|
|
||||||
@include text-sizing(20px, 700, 24px);
|
|
||||||
|
|
||||||
body.theme-gabsocial-light & {
|
|
||||||
color: $gab-default-text-light;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover & {
|
|
||||||
&__name {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__username {
|
|
||||||
display: block;
|
|
||||||
color: $gab-secondary-text;
|
|
||||||
text-decoration: none !important;
|
|
||||||
|
|
||||||
@include text-sizing(14px, 16px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__stats-block {
|
|
||||||
padding-top: 12px;
|
|
||||||
|
|
||||||
@include flex(space-between);
|
|
||||||
}
|
|
||||||
|
|
||||||
.user-panel-stats-item {
|
|
||||||
flex-wrap: wrap;
|
|
||||||
|
|
||||||
@include flex(left, start, column);
|
|
||||||
|
|
||||||
a {
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
color: $primary-text-color;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__value {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
color: #fff;
|
|
||||||
|
|
||||||
@include text-sizing(20px, 800, 24px);
|
|
||||||
|
|
||||||
body.theme-gabsocial-light & {
|
|
||||||
color: $gab-default-text-light;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__label {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
color: $gab-secondary-text;
|
|
||||||
|
|
||||||
@include text-sizing(12px, 400, 14px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export { default } from './verified_icon';
|
|
|
@ -1,13 +0,0 @@
|
||||||
import './verified_icon.scss';
|
|
||||||
|
|
||||||
export default class VerifiedIcon extends PureComponent {
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<span className='verified-icon'>
|
|
||||||
<span className='invisible'>Verified Account</span>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
|
@ -1,28 +0,0 @@
|
||||||
.verified-icon {
|
|
||||||
display: inline-block;
|
|
||||||
margin-top: 1px;
|
|
||||||
margin-left: 4px;
|
|
||||||
vertical-align: top;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
@include size(15px);
|
|
||||||
|
|
||||||
&:before {
|
|
||||||
background-color: #00A3ED;
|
|
||||||
border-radius: 50%;
|
|
||||||
|
|
||||||
@include pseudo;
|
|
||||||
@include abs-position(0, 0, 0, 0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:after {
|
|
||||||
font: normal normal normal 14px/1 FontAwesome;
|
|
||||||
text-rendering: auto;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
color: #fff;
|
|
||||||
|
|
||||||
@include pseudo('\f00c');
|
|
||||||
@include size(15px);
|
|
||||||
@include text-sizing(0.6em, 400, 15px, center);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,3 @@
|
||||||
import './zoomable_image.scss';
|
|
||||||
|
|
||||||
const MIN_SCALE = 1;
|
const MIN_SCALE = 1;
|
||||||
const MAX_SCALE = 4;
|
const MAX_SCALE = 4;
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,6 @@ import MediaItem from './components/media_item';
|
||||||
import LoadMore from '../../components/load_more';
|
import LoadMore from '../../components/load_more';
|
||||||
import SectionHeadlineBar from '../../components/section_headline_bar';
|
import SectionHeadlineBar from '../../components/section_headline_bar';
|
||||||
|
|
||||||
import './account_gallery.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
posts: { id: 'account.posts', defaultMessage: 'Gabs' },
|
posts: { id: 'account.posts', defaultMessage: 'Gabs' },
|
||||||
postsWithReplies: { id: 'account.posts_with_replies', defaultMessage: 'Gabs and replies' },
|
postsWithReplies: { id: 'account.posts_with_replies', defaultMessage: 'Gabs and replies' },
|
||||||
|
|
|
@ -6,8 +6,6 @@ import Icon from '../../../../components/icon';
|
||||||
import { autoPlayGif, displayMedia } from '../../../../initial_state';
|
import { autoPlayGif, displayMedia } from '../../../../initial_state';
|
||||||
import { isIOS } from '../../../../utils/is_mobile';
|
import { isIOS } from '../../../../utils/is_mobile';
|
||||||
|
|
||||||
import './media_item.scss';
|
|
||||||
|
|
||||||
export default class MediaItem extends ImmutablePureComponent {
|
export default class MediaItem extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -3,8 +3,6 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import InnerHeader from '../inner_header';
|
import InnerHeader from '../inner_header';
|
||||||
import MovedNote from '../moved_note';
|
import MovedNote from '../moved_note';
|
||||||
|
|
||||||
import './header.scss';
|
|
||||||
|
|
||||||
export default class Header extends ImmutablePureComponent {
|
export default class Header extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
export { default } from './inner_header.scss';
|
export { default } from './inner_header';
|
||||||
|
|
|
@ -11,8 +11,6 @@ import { shortNumberFormat } from '../../../utils/numbers';
|
||||||
import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
|
import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
|
||||||
import ProfileInfoPanel from './profile_info_panel/profile_info_panel';
|
import ProfileInfoPanel from './profile_info_panel/profile_info_panel';
|
||||||
|
|
||||||
import './inner_header.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||||
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||||
|
|
|
@ -6,8 +6,6 @@ import AvatarOverlay from '../../../../components/avatar_overlay';
|
||||||
import DisplayName from '../../../../components/display_name';
|
import DisplayName from '../../../../components/display_name';
|
||||||
import Icon from '../../../../components/icon';
|
import Icon from '../../../../components/icon';
|
||||||
|
|
||||||
import './moved_note.scss';
|
|
||||||
|
|
||||||
export default class MovedNote extends ImmutablePureComponent {
|
export default class MovedNote extends ImmutablePureComponent {
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
|
|
|
@ -6,8 +6,6 @@ import Icon from '../../../../components/icon';
|
||||||
import VerifiedIcon from '../../../../components/verified_icon';
|
import VerifiedIcon from '../../../../components/verified_icon';
|
||||||
import Badge from '../../../../components/badge';
|
import Badge from '../../../../components/badge';
|
||||||
|
|
||||||
import './profile_info_panel.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' },
|
linkVerifiedOn: { id: 'account.link_verified_on', defaultMessage: 'Ownership of this link was checked on {date}' },
|
||||||
account_locked: { id: 'account.locked_info', defaultMessage: 'This account privacy status is set to locked. The owner manually reviews who can follow them.' },
|
account_locked: { id: 'account.locked_info', defaultMessage: 'This account privacy status is set to locked. The owner manually reviews who can follow them.' },
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { length } from 'stringz';
|
import { length } from 'stringz';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
|
||||||
import './character_counter.scss';
|
|
||||||
|
|
||||||
export default class CharacterCounter extends PureComponent {
|
export default class CharacterCounter extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
import classNames from 'classnames/bind'
|
||||||
|
import Icon from '../../../components/icon'
|
||||||
|
|
||||||
|
export default class ComposeExtraButton extends PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
title: PropTypes.string,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
onClick: PropTypes.func,
|
||||||
|
icon: PropTypes.string,
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
hovering: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseEnter = () => {
|
||||||
|
this.setState({ hovering: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseLeave = () => {
|
||||||
|
this.setState({ hovering: false })
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { title, disabled, onClick, icon, children } = this.props
|
||||||
|
const { hovering } = this.state
|
||||||
|
|
||||||
|
const cx = classNames.bind(styles)
|
||||||
|
|
||||||
|
const btnClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
circle: 1,
|
||||||
|
flexRow: 1,
|
||||||
|
paddingVertical10PX: 1,
|
||||||
|
paddingHorizontal10PX: 1,
|
||||||
|
cursorPointer: 1,
|
||||||
|
backgroundSubtle: !hovering,
|
||||||
|
backgroundSubtle2: hovering,
|
||||||
|
})
|
||||||
|
|
||||||
|
const titleClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
marginLeft5PX: 1,
|
||||||
|
text: 1,
|
||||||
|
lineHeight15: 1,
|
||||||
|
fontSize12PX: 1,
|
||||||
|
fontWeight500: 1,
|
||||||
|
colorSubtle: 1,
|
||||||
|
displayNone: !hovering,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[styles.default, styles.marginRight10PX].join(' ')}>
|
||||||
|
<button
|
||||||
|
className={btnClasses}
|
||||||
|
title={title}
|
||||||
|
disabled={disabled}
|
||||||
|
onClick={onClick}
|
||||||
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
|
>
|
||||||
|
<Icon icon={icon} width='18px' height='18px' />
|
||||||
|
<span className={titleClasses}>
|
||||||
|
{title}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,22 +7,20 @@ import CharacterCounter from '../character_counter';
|
||||||
import UploadForm from '../upload_form';
|
import UploadForm from '../upload_form';
|
||||||
import ReplyIndicatorContainer from '../../containers/reply_indicator_container';
|
import ReplyIndicatorContainer from '../../containers/reply_indicator_container';
|
||||||
import AutosuggestTextbox from '../../../../components/autosuggest_textbox';
|
import AutosuggestTextbox from '../../../../components/autosuggest_textbox';
|
||||||
import PollButtonContainer from '../../containers/poll_button_container';
|
import PollButton from '../../components/poll_button';
|
||||||
import UploadButtonContainer from '../../containers/upload_button_container';
|
import UploadButton from '../../components/upload_button';
|
||||||
import SpoilerButtonContainer from '../../containers/spoiler_button_container';
|
import SpoilerButton from '../../components/spoiler_button';
|
||||||
import PrivacyDropdownContainer from '../../containers/privacy_dropdown_container';
|
import PrivacyDropdown from '../../components/privacy_dropdown';
|
||||||
import EmojiPickerDropdown from '../../containers/emoji_picker_dropdown_container';
|
import EmojiPickerDropdown from '../../containers/emoji_picker_dropdown_container';
|
||||||
import PollFormContainer from '../../containers/poll_form_container';
|
import PollFormContainer from '../../containers/poll_form_container';
|
||||||
import WarningContainer from '../../containers/warning_container';
|
import WarningContainer from '../../containers/warning_container';
|
||||||
import SchedulePostDropdownContainer from '../../containers/schedule_post_dropdown_container';
|
import SchedulePostDropdown from '../../components/schedule_post_dropdown';
|
||||||
import QuotedStatusPreviewContainer from '../../containers/quoted_status_preview_container';
|
import QuotedStatusPreviewContainer from '../../containers/quoted_status_preview_container';
|
||||||
import Icon from '../../../../components/icon';
|
import Icon from '../../../../components/icon';
|
||||||
import Button from '../../../../components/button';
|
import Button from '../../../../components/button';
|
||||||
import { isMobile } from '../../../../utils/is_mobile';
|
import { isMobile } from '../../../../utils/is_mobile';
|
||||||
import { countableText } from '../../util/counter';
|
import { countableText } from '../../util/counter';
|
||||||
|
|
||||||
import './compose_form.scss';
|
|
||||||
|
|
||||||
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
|
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
|
||||||
const maxPostCharacterCount = 3000;
|
const maxPostCharacterCount = 3000;
|
||||||
|
|
||||||
|
@ -30,7 +28,7 @@ const messages = defineMessages({
|
||||||
placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What is on your mind?' },
|
placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What is on your mind?' },
|
||||||
spoiler_placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Write your warning here' },
|
spoiler_placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Write your warning here' },
|
||||||
publish: { id: 'compose_form.publish', defaultMessage: 'Gab' },
|
publish: { id: 'compose_form.publish', defaultMessage: 'Gab' },
|
||||||
publishLoud: { id: 'compose_form.publish_loud', defaultMessage: '{publish}!' },
|
publishLoud: { id: 'compose_form.publish_loud', defaultMessage: '{publish}' },
|
||||||
schedulePost: { id: 'compose_form.schedule_post', defaultMessage: 'Schedule Post' }
|
schedulePost: { id: 'compose_form.schedule_post', defaultMessage: 'Schedule Post' }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -220,29 +218,22 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
const disabledButton = disabled || this.props.isUploading || this.props.isChangingUpload || length(text) > maxPostCharacterCount || (text.length !== 0 && text.trim().length === 0 && !anyMedia);
|
const disabledButton = disabled || this.props.isUploading || this.props.isChangingUpload || length(text) > maxPostCharacterCount || (text.length !== 0 && text.trim().length === 0 && !anyMedia);
|
||||||
const shouldAutoFocus = autoFocus && !showSearch && !isMobile(window.innerWidth)
|
const shouldAutoFocus = autoFocus && !showSearch && !isMobile(window.innerWidth)
|
||||||
|
|
||||||
let publishText = '';
|
|
||||||
|
|
||||||
if (this.props.privacy === 'private' || this.props.privacy === 'direct') {
|
|
||||||
publishText = <span className='compose-form__publish-private'><Icon id='lock' /> {intl.formatMessage(messages.publish)}</span>;
|
|
||||||
} else {
|
|
||||||
publishText = this.props.privacy !== 'unlisted' ? intl.formatMessage(messages.publishLoud, { publish: intl.formatMessage(messages.publish) }) : intl.formatMessage(messages.publish);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (scheduledAt) {
|
|
||||||
publishText = intl.formatMessage(messages.schedulePost);
|
|
||||||
}
|
|
||||||
|
|
||||||
const composeClassNames = classNames({
|
const composeClassNames = classNames({
|
||||||
'compose-form': true,
|
'compose-form': true,
|
||||||
'condensed': condensed,
|
'condensed': condensed,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={composeClassNames} ref={this.setForm} onClick={this.handleClick}>
|
<div
|
||||||
<WarningContainer />
|
className={[styles.default, styles.flexGrow1].join(' ')}
|
||||||
|
ref={this.setForm}
|
||||||
|
onClick={this.handleClick}
|
||||||
|
>
|
||||||
|
{ /* <WarningContainer /> */ }
|
||||||
|
|
||||||
{ !shouldCondense && <ReplyIndicatorContainer /> }
|
{ /* !shouldCondense && <ReplyIndicatorContainer /> */ }
|
||||||
|
|
||||||
|
{ /*
|
||||||
<div className={`spoiler-input ${this.props.spoiler ? 'spoiler-input--visible' : ''}`}>
|
<div className={`spoiler-input ${this.props.spoiler ? 'spoiler-input--visible' : ''}`}>
|
||||||
<AutosuggestTextbox
|
<AutosuggestTextbox
|
||||||
placeholder={intl.formatMessage(messages.spoiler_placeholder)}
|
placeholder={intl.formatMessage(messages.spoiler_placeholder)}
|
||||||
|
@ -260,13 +251,14 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
className='spoiler-input__input'
|
className='spoiler-input__input'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
*/ }
|
||||||
|
|
||||||
|
{ /*
|
||||||
<div className='emoji-picker-wrapper'>
|
<div className='emoji-picker-wrapper'>
|
||||||
<EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} />
|
<EmojiPickerDropdown onPickEmoji={this.handleEmojiPick} />
|
||||||
</div>
|
</div> */ }
|
||||||
|
|
||||||
<AutosuggestTextbox
|
<AutosuggestTextbox
|
||||||
textarea={true}
|
|
||||||
ref={(isModalOpen && shouldCondense) ? null : this.setAutosuggestTextarea}
|
ref={(isModalOpen && shouldCondense) ? null : this.setAutosuggestTextarea}
|
||||||
placeholder={intl.formatMessage(messages.placeholder)}
|
placeholder={intl.formatMessage(messages.placeholder)}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
@ -280,38 +272,37 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
onSuggestionSelected={this.onSuggestionSelected}
|
onSuggestionSelected={this.onSuggestionSelected}
|
||||||
onPaste={onPaste}
|
onPaste={onPaste}
|
||||||
autoFocus={shouldAutoFocus}
|
autoFocus={shouldAutoFocus}
|
||||||
|
textarea
|
||||||
>
|
>
|
||||||
{
|
{ /*
|
||||||
!condensed &&
|
!condensed &&
|
||||||
<div className='compose-form__modifiers'>
|
<div className='compose-form__modifiers'>
|
||||||
<UploadForm />
|
<UploadForm />
|
||||||
{!edit && <PollFormContainer />}
|
{!edit && <PollFormContainer />}
|
||||||
</div>
|
</div>
|
||||||
}
|
*/ }
|
||||||
</AutosuggestTextbox>
|
</AutosuggestTextbox>
|
||||||
|
|
||||||
{quoteOfId && <QuotedStatusPreviewContainer id={quoteOfId} />}
|
{ /* quoteOfId && <QuotedStatusPreviewContainer id={quoteOfId} /> */ }
|
||||||
|
|
||||||
{
|
{
|
||||||
!condensed &&
|
/* !condensed && */
|
||||||
<div className='compose-form__buttons-wrapper'>
|
<div className={[styles.default, styles.flexRow, styles.marginTop10PX].join(' ')}>
|
||||||
<div className='compose-form__buttons'>
|
<div className={[styles.default, styles.flexRow, styles.marginRightAuto].join(' ')}>
|
||||||
<UploadButtonContainer />
|
<UploadButton />
|
||||||
{!edit && <PollButtonContainer />}
|
{
|
||||||
<PrivacyDropdownContainer />
|
!edit && <PollButton />
|
||||||
<SpoilerButtonContainer />
|
}
|
||||||
<SchedulePostDropdownContainer
|
<PrivacyDropdown />
|
||||||
position={isModalOpen ? 'top' : undefined}
|
<SpoilerButton />
|
||||||
/>
|
<SchedulePostDropdown position={isModalOpen ? 'top' : undefined} />
|
||||||
</div>
|
</div>
|
||||||
<CharacterCounter max={maxPostCharacterCount} text={text} />
|
<CharacterCounter max={maxPostCharacterCount} text={text} />
|
||||||
</div>
|
<Button
|
||||||
}
|
text={intl.formatMessage(scheduledAt ? messages.schedulePost : messages.publish)}
|
||||||
|
onClick={this.handleSubmit}
|
||||||
{
|
disabled={disabledButton}
|
||||||
!condensed &&
|
/>
|
||||||
<div className='compose-form__publish'>
|
|
||||||
<div className='compose-form__publish-button-wrapper'><Button text={publishText} onClick={this.handleSubmit} disabled={disabledButton} block /></div>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,6 @@ import Overlay from 'react-overlays/lib/Overlay';
|
||||||
import { EmojiPicker as EmojiPickerAsync } from '../../../ui/util/async-components';
|
import { EmojiPicker as EmojiPickerAsync } from '../../../ui/util/async-components';
|
||||||
import { buildCustomEmojis } from '../../../../components/emoji/emoji';
|
import { buildCustomEmojis } from '../../../../components/emoji/emoji';
|
||||||
|
|
||||||
import './emoji_picker_dropdown.scss';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
|
emoji: { id: 'emoji_button.label', defaultMessage: 'Insert emoji' },
|
||||||
emoji_search: { id: 'emoji_button.search', defaultMessage: 'Search...' },
|
emoji_search: { id: 'emoji_button.search', defaultMessage: 'Search...' },
|
||||||
|
|
|
@ -7,8 +7,6 @@ import Permalink from '../../../../components/permalink';
|
||||||
import IconButton from '../../../../components/icon_button';
|
import IconButton from '../../../../components/icon_button';
|
||||||
import { me } from '../../../../initial_state';
|
import { me } from '../../../../initial_state';
|
||||||
|
|
||||||
import './navigation_bar.scss';
|
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
return {
|
return {
|
||||||
account: state.getIn(['accounts', me]),
|
account: state.getIn(['accounts', me]),
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue