Progress
This commit is contained in:
parent
65af72faae
commit
0d9dbdfecd
@ -13,7 +13,6 @@ export const MUTES_EXPAND_SUCCESS = 'MUTES_EXPAND_SUCCESS';
|
|||||||
export const MUTES_EXPAND_FAIL = 'MUTES_EXPAND_FAIL';
|
export const MUTES_EXPAND_FAIL = 'MUTES_EXPAND_FAIL';
|
||||||
|
|
||||||
export const MUTES_INIT_MODAL = 'MUTES_INIT_MODAL';
|
export const MUTES_INIT_MODAL = 'MUTES_INIT_MODAL';
|
||||||
export const MUTES_TOGGLE_HIDE_NOTIFICATIONS = 'MUTES_TOGGLE_HIDE_NOTIFICATIONS';
|
|
||||||
|
|
||||||
export function fetchMutes() {
|
export function fetchMutes() {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
@ -103,9 +102,3 @@ export function initMuteModal(account) {
|
|||||||
dispatch(openModal('MUTE'));
|
dispatch(openModal('MUTE'));
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toggleHideNotifications() {
|
|
||||||
return dispatch => {
|
|
||||||
dispatch({ type: MUTES_TOGGLE_HIDE_NOTIFICATIONS });
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
@ -110,7 +110,7 @@ class Account extends ImmutablePureComponent {
|
|||||||
const blocking = account.getIn(['relationship', 'blocking'])
|
const blocking = account.getIn(['relationship', 'blocking'])
|
||||||
|
|
||||||
if (requested || blocking) {
|
if (requested || blocking) {
|
||||||
buttonText = intl.formatMessage(requested ? messages.requested : messages.blocking)
|
buttonText = intl.formatMessage(requested ? messages.requested : messages.unblock)
|
||||||
buttonOptions = {
|
buttonOptions = {
|
||||||
narrow: true,
|
narrow: true,
|
||||||
onClick: requested ? this.handleUnrequest : this.handleBlock,
|
onClick: requested ? this.handleUnrequest : this.handleBlock,
|
||||||
|
@ -260,10 +260,10 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<ContentEditable
|
<ContentEditable
|
||||||
tabindex='0'
|
tabIndex='0'
|
||||||
ariaLabel='Gab text'
|
aria-label='Gab text'
|
||||||
role='textbox'
|
role='textbox'
|
||||||
ariaAutocomplete='list'
|
aria-autocomplete='list'
|
||||||
style={{
|
style={{
|
||||||
userSelect: 'text',
|
userSelect: 'text',
|
||||||
'white-space': 'pre-wrap',
|
'white-space': 'pre-wrap',
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import IconButton from '../icon_button';
|
import IconButton from './icon_button'
|
||||||
|
|
||||||
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.' },
|
||||||
retry: { id: 'bundle_column_error.retry', defaultMessage: 'Try again' },
|
retry: { id: 'bundle_column_error.retry', defaultMessage: 'Try again' },
|
||||||
});
|
})
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@injectIntl
|
@injectIntl
|
||||||
@ -17,18 +17,18 @@ class BundleColumnError extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleRetry = () => {
|
handleRetry = () => {
|
||||||
this.props.onRetry();
|
this.props.onRetry()
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl: { formatMessage } } = this.props;
|
const { intl: { formatMessage } } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='error-column'>
|
<div className='error-column'>
|
||||||
<IconButton title={formatMessage(messages.retry)} icon='refresh' onClick={this.handleRetry} size={64} />
|
<IconButton title={formatMessage(messages.retry)} icon='refresh' onClick={this.handleRetry} size={64} />
|
||||||
{formatMessage(messages.body)}
|
{formatMessage(messages.body)}
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,29 +0,0 @@
|
|||||||
.error-column {
|
|
||||||
color: $dark-text-color;
|
|
||||||
background: $ui-base-color;
|
|
||||||
padding: 40px;
|
|
||||||
cursor: default;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
min-height: 160px;
|
|
||||||
|
|
||||||
@include flex(center, center, column);
|
|
||||||
@include text-sizing(15px, 400, 1, center);
|
|
||||||
|
|
||||||
@supports(display: grid) {
|
|
||||||
// hack to fix Chrome <57
|
|
||||||
contain: strict;
|
|
||||||
}
|
|
||||||
|
|
||||||
&>span {
|
|
||||||
max-width: 400px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: $highlight-text-color;
|
|
||||||
text-decoration: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
export { default } from './bundle_column_error'
|
|
@ -69,7 +69,7 @@ export default class ColumnHeader extends PureComponent {
|
|||||||
<Button
|
<Button
|
||||||
radiusSmall
|
radiusSmall
|
||||||
backgroundColor='tertiary'
|
backgroundColor='tertiary'
|
||||||
onClick={() => action.onClick()}
|
onClick={() => action.onClick() }
|
||||||
key={`column-header-action-btn-${i}`}
|
key={`column-header-action-btn-${i}`}
|
||||||
className={[_s.ml5, _s.px10].join(' ')}
|
className={[_s.ml5, _s.px10].join(' ')}
|
||||||
iconClassName={_s.fillColorSecondary}
|
iconClassName={_s.fillColorSecondary}
|
||||||
|
@ -21,7 +21,7 @@ export default
|
|||||||
class DisplayName extends ImmutablePureComponent {
|
class DisplayName extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
account: ImmutablePropTypes.map.isRequired,
|
account: ImmutablePropTypes.map,
|
||||||
openUserInfoPopover: PropTypes.func.isRequired,
|
openUserInfoPopover: PropTypes.func.isRequired,
|
||||||
closeUserInfoPopover: PropTypes.func.isRequired,
|
closeUserInfoPopover: PropTypes.func.isRequired,
|
||||||
multiline: PropTypes.bool,
|
multiline: PropTypes.bool,
|
||||||
@ -32,7 +32,6 @@ class DisplayName extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleMouseEnter = debounce(() => {
|
handleMouseEnter = debounce(() => {
|
||||||
console.log("SHOW - USER POPOVER")
|
|
||||||
this.props.openUserInfoPopover({
|
this.props.openUserInfoPopover({
|
||||||
targetRef: this.node,
|
targetRef: this.node,
|
||||||
position: 'top',
|
position: 'top',
|
||||||
@ -41,7 +40,6 @@ class DisplayName extends ImmutablePureComponent {
|
|||||||
}, 1000, { leading: true })
|
}, 1000, { leading: true })
|
||||||
|
|
||||||
handleMouseLeave = debounce(() => {
|
handleMouseLeave = debounce(() => {
|
||||||
console.log("HIDE - USER POPOVER")
|
|
||||||
this.props.closeUserInfoPopover()
|
this.props.closeUserInfoPopover()
|
||||||
}, 1000, { leading: true })
|
}, 1000, { leading: true })
|
||||||
|
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
import { is } from 'immutable';
|
import { is } from 'immutable'
|
||||||
import { setHeight } from '../actions/height_cache';
|
import { setHeight } from '../actions/height_cache'
|
||||||
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'
|
||||||
|
|
||||||
// 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
|
||||||
const updateOnPropsForUnrendered = ['id', 'index', 'listLength', 'cachedHeight'];
|
const updateOnPropsForUnrendered = ['id', 'index', 'listLength', 'cachedHeight']
|
||||||
|
|
||||||
const makeMapStateToProps = (state, props) => ({
|
const makeMapStateToProps = (state, props) => ({
|
||||||
cachedHeight: state.getIn(['height_cache', props.saveHeightKey, props.id]),
|
cachedHeight: state.getIn(['height_cache', props.saveHeightKey, props.id]),
|
||||||
});
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
|
||||||
onHeightChange (key, id, height) {
|
onHeightChange(key, id, height) {
|
||||||
dispatch(setHeight(key, id, height));
|
dispatch(setHeight(key, id, height))
|
||||||
},
|
},
|
||||||
|
|
||||||
});
|
})
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@connect(makeMapStateToProps, mapDispatchToProps)
|
@connect(makeMapStateToProps, mapDispatchToProps)
|
||||||
@ -33,13 +33,13 @@ class IntersectionObserverArticle extends Component {
|
|||||||
cachedHeight: PropTypes.number,
|
cachedHeight: PropTypes.number,
|
||||||
onHeightChange: PropTypes.func,
|
onHeightChange: PropTypes.func,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
};
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
isHidden: false, // set to true in requestIdleCallback to trigger un-render
|
isHidden: false, // set to true in requestIdleCallback to trigger un-render
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldComponentUpdate (nextProps, nextState) {
|
shouldComponentUpdate(nextProps, nextState) {
|
||||||
const isUnrendered = !this.state.isIntersecting && (this.state.isHidden || this.props.cachedHeight);
|
const isUnrendered = !this.state.isIntersecting && (this.state.isHidden || this.props.cachedHeight);
|
||||||
const willBeUnrendered = !nextState.isIntersecting && (nextState.isHidden || nextProps.cachedHeight);
|
const willBeUnrendered = !nextState.isIntersecting && (nextState.isHidden || nextProps.cachedHeight);
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ class IntersectionObserverArticle extends Component {
|
|||||||
return !propsToDiff.every(prop => is(nextProps[prop], this.props[prop]));
|
return !propsToDiff.every(prop => is(nextProps[prop], this.props[prop]));
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount() {
|
||||||
const { intersectionObserverWrapper, id } = this.props;
|
const { intersectionObserverWrapper, id } = this.props;
|
||||||
|
|
||||||
intersectionObserverWrapper.observe(
|
intersectionObserverWrapper.observe(
|
||||||
@ -65,7 +65,7 @@ class IntersectionObserverArticle extends Component {
|
|||||||
this.componentMounted = true;
|
this.componentMounted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount () {
|
componentWillUnmount() {
|
||||||
const { intersectionObserverWrapper, id } = this.props;
|
const { intersectionObserverWrapper, id } = this.props;
|
||||||
intersectionObserverWrapper.unobserve(id, this.node);
|
intersectionObserverWrapper.unobserve(id, this.node);
|
||||||
|
|
||||||
@ -91,32 +91,32 @@ class IntersectionObserverArticle extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
calculateHeight = () => {
|
calculateHeight = () => {
|
||||||
const { onHeightChange, saveHeightKey, id } = this.props;
|
const { onHeightChange, saveHeightKey, id } = this.props
|
||||||
// Save the height of the fully-rendered element (this is expensive
|
// Save the height of the fully-rendered element (this is expensive
|
||||||
// on Chrome, where we need to fall back to getBoundingClientRect)
|
// on Chrome, where we need to fall back to getBoundingClientRect)
|
||||||
this.height = getRectFromEntry(this.entry).height;
|
this.height = getRectFromEntry(this.entry).height
|
||||||
|
|
||||||
if (onHeightChange && saveHeightKey) {
|
if (onHeightChange && saveHeightKey) {
|
||||||
onHeightChange(saveHeightKey, id, this.height);
|
onHeightChange(saveHeightKey, id, this.height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hideIfNotIntersecting = () => {
|
hideIfNotIntersecting = () => {
|
||||||
if (!this.componentMounted) return;
|
if (!this.componentMounted) return
|
||||||
|
|
||||||
// When the browser gets a chance, test if we're still not intersecting,
|
// When the browser gets a chance, test if we're still not intersecting,
|
||||||
// and if so, set our isHidden to true to trigger an unrender. The point of
|
// and if so, set our isHidden to true to trigger an unrender. The point of
|
||||||
// this is to save DOM nodes and avoid using up too much memory.
|
// this is to save DOM nodes and avoid using up too much memory.
|
||||||
this.setState((prevState) => ({ isHidden: !prevState.isIntersecting }));
|
this.setState((prevState) => ({ isHidden: !prevState.isIntersecting }))
|
||||||
}
|
}
|
||||||
|
|
||||||
handleRef = (node) => {
|
handleRef = (node) => {
|
||||||
this.node = node;
|
this.node = node
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render() {
|
||||||
const { children, id, index, listLength, cachedHeight } = this.props;
|
const { children, id, index, listLength, cachedHeight } = this.props
|
||||||
const { isIntersecting, isHidden } = this.state;
|
const { isIntersecting, isHidden } = this.state
|
||||||
|
|
||||||
if (!isIntersecting && (isHidden || cachedHeight)) {
|
if (!isIntersecting && (isHidden || cachedHeight)) {
|
||||||
return (
|
return (
|
||||||
@ -130,7 +130,7 @@ class IntersectionObserverArticle extends Component {
|
|||||||
>
|
>
|
||||||
{children && React.cloneElement(children, { hidden: true })}
|
{children && React.cloneElement(children, { hidden: true })}
|
||||||
</article>
|
</article>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -143,7 +143,7 @@ class IntersectionObserverArticle extends Component {
|
|||||||
>
|
>
|
||||||
{children && React.cloneElement(children, { hidden: false })}
|
{children && React.cloneElement(children, { hidden: false })}
|
||||||
</article>
|
</article>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,16 +7,27 @@ const cx = classNames.bind(_s)
|
|||||||
|
|
||||||
export default class ListItem extends PureComponent {
|
export default class ListItem extends PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
icon: PropTypes.string,
|
||||||
isLast: PropTypes.bool,
|
isLast: PropTypes.bool,
|
||||||
to: PropTypes.string,
|
to: PropTypes.string,
|
||||||
href: PropTypes.string,
|
href: PropTypes.string,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
onClick: PropTypes.func,
|
onClick: PropTypes.func,
|
||||||
small: PropTypes.bool,
|
small: PropTypes.bool,
|
||||||
|
hideArrow: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { title, isLast, to, href, onClick, small } = this.props
|
const {
|
||||||
|
title,
|
||||||
|
isLast,
|
||||||
|
to,
|
||||||
|
href,
|
||||||
|
onClick,
|
||||||
|
small,
|
||||||
|
icon,
|
||||||
|
hideArrow,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
const containerClasses = cx({
|
const containerClasses = cx({
|
||||||
default: 1,
|
default: 1,
|
||||||
@ -44,16 +55,30 @@ export default class ListItem extends PureComponent {
|
|||||||
className={containerClasses}
|
className={containerClasses}
|
||||||
noClasses
|
noClasses
|
||||||
>
|
>
|
||||||
|
|
||||||
|
{
|
||||||
|
!!icon &&
|
||||||
|
<Icon
|
||||||
|
id={icon}
|
||||||
|
width='10px'
|
||||||
|
height='10px'
|
||||||
|
className={[_s.mr10, _s.fillColorBlack].join(' ')}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
|
||||||
<Text color='primary' size={textSize}>
|
<Text color='primary' size={textSize}>
|
||||||
{title}
|
{title}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
|
{
|
||||||
|
!hideArrow &&
|
||||||
<Icon
|
<Icon
|
||||||
id='angle-right'
|
id='angle-right'
|
||||||
width='10px'
|
width='10px'
|
||||||
height='10px'
|
height='10px'
|
||||||
className={[_s.marginLeftAuto, _s.fillColorBlack].join(' ')}
|
className={[_s.marginLeftAuto, _s.fillColorBlack].join(' ')}
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
</Button>
|
</Button>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import Button from '../button'
|
||||||
|
import Text from '../text'
|
||||||
|
import ModalLayout from './modal_layout'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: { id: 'promo.gab_pro', defaultMessage: 'Upgrade to GabPRO' },
|
||||||
|
text: { id: 'pro_upgrade_modal.text', defaultMessage: 'Gab is fully funded by people like you. Please consider supporting us on our mission to defend free expression online for all people.' },
|
||||||
|
benefits: { id: 'pro_upgrade_modal.benefits', defaultMessage: 'Here are just some of the benefits that thousands of GabPRO members receive:' },
|
||||||
|
})
|
||||||
|
|
||||||
|
export default
|
||||||
|
@injectIntl
|
||||||
|
class HomeTimelineSettingsModal extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { intl } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Text>
|
||||||
|
{intl.formatMessage(messages.text)}
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
{intl.formatMessage(messages.benefits)}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<div className={[_s.default, _s.my10].join(' ')}>
|
||||||
|
<Text>• Schedule Posts</Text>
|
||||||
|
<Text>• Get Verified</Text>
|
||||||
|
<Text>• Create Groups</Text>
|
||||||
|
<Text>• Larger Video and Image Uploads</Text>
|
||||||
|
<Text>• Receive the PRO Badge</Text>
|
||||||
|
<Text>• Remove in-feed promotions</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
centered
|
||||||
|
backgroundColor='brand'
|
||||||
|
color='white'
|
||||||
|
icon='pro'
|
||||||
|
href='https://pro.gab.com'
|
||||||
|
className={_s.justifyContentCenter}
|
||||||
|
iconClassName={[_s.mr5, _s.fillColorWhite].join(' ')}
|
||||||
|
>
|
||||||
|
<Text color='inherit' weight='bold' align='center'>
|
||||||
|
{intl.formatMessage(messages.title)}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import { makeGetAccount } from '../../selectors'
|
||||||
|
import { closeModal } from '../../actions/modal'
|
||||||
|
import { blockAccount } from '../../actions/accounts'
|
||||||
|
import ConfirmationModal from './confirmation_modal'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: { id: 'block_title', defaultMessage: 'Block {name}' },
|
||||||
|
muteMessage: { id: 'confirmations.block.message', defaultMessage: 'Are you sure you want to block {name}?' },
|
||||||
|
block: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapStateToProps = (state, { accountId }) => {
|
||||||
|
const getAccount = makeGetAccount()
|
||||||
|
|
||||||
|
return {
|
||||||
|
account: getAccount(state, accountId),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
onConfirm(account) {
|
||||||
|
dispatch(blockAccount(account.get('id')))
|
||||||
|
},
|
||||||
|
onClose() {
|
||||||
|
dispatch(closeModal())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
@injectIntl
|
||||||
|
class BlockAccountModal extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
account: PropTypes.object.isRequired,
|
||||||
|
onConfirm: PropTypes.func.isRequired,
|
||||||
|
onClose: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick = () => {
|
||||||
|
this.props.onConfirm(this.props.account)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClose = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { account, intl } = this.props
|
||||||
|
|
||||||
|
const title = intl.formatMessage(messages.title, {
|
||||||
|
name: !!account ? account.get('acct') : '',
|
||||||
|
})
|
||||||
|
const message = intl.formatMessage(messages.muteMessage, {
|
||||||
|
name: !!account ? account.get('acct') : '',
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmationModal
|
||||||
|
title={title}
|
||||||
|
message={message}
|
||||||
|
confirm={intl.formatMessage(messages.block)}
|
||||||
|
onClose={this.handleClose}
|
||||||
|
onConfirm={this.handleClick}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import { muteAccount } from '../../actions/accounts'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
||||||
|
cancel: { id: 'confirmation_modal.cancel', defaultMessage: 'Cancel' },
|
||||||
|
confirm: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
|
||||||
|
account: state.getIn(['mutes', 'new', 'account']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
onConfirm(account, notifications) {
|
||||||
|
dispatch(muteAccount(account.get('id'), notifications))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
@injectIntl
|
||||||
|
class BlockDomainModal extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
isSubmitting: PropTypes.bool.isRequired,
|
||||||
|
account: PropTypes.object.isRequired,
|
||||||
|
onConfirm: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.button.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
this.props.onConfirm(this.props.account, this.props.notifications)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCancel = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { account, intl } = this.props
|
||||||
|
|
||||||
|
// dispatch(openModal('CONFIRM', {
|
||||||
|
// message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.' values={{ domain: <strong>{domain}</strong> }} />,
|
||||||
|
// confirm: intl.formatMessage(messages.blockDomainConfirm),
|
||||||
|
// onConfirm: () => dispatch(blockDomain(domain)),
|
||||||
|
// }));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmationModal
|
||||||
|
title={`Mute @${account.get('acct')}`}
|
||||||
|
message={<FormattedMessage id='confirmations.mute.message' defaultMessage='Are you sure you want to mute @{name}?' values={{ name: account.get('acct') }} />}
|
||||||
|
confirm={<FormattedMessage id='mute' defaultMessage='Mute' />}
|
||||||
|
onConfirm={() => {
|
||||||
|
// dispatch(blockDomain(domain))
|
||||||
|
// dispatch(blockDomain(domain))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import { muteAccount } from '../../actions/accounts'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
||||||
|
cancel: { id: 'confirmation_modal.cancel', defaultMessage: 'Cancel' },
|
||||||
|
confirm: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
|
||||||
|
account: state.getIn(['mutes', 'new', 'account']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
onConfirm(account, notifications) {
|
||||||
|
dispatch(muteAccount(account.get('id'), notifications))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
@injectIntl
|
||||||
|
class UnfollowModal extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
isSubmitting: PropTypes.bool.isRequired,
|
||||||
|
account: PropTypes.object.isRequired,
|
||||||
|
onConfirm: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.button.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
this.props.onConfirm(this.props.account, this.props.notifications)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCancel = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { account, intl } = this.props
|
||||||
|
|
||||||
|
// , {
|
||||||
|
// message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
||||||
|
// confirm: intl.formatMessage(messages.unfollowConfirm),
|
||||||
|
// onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
|
||||||
|
// }));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmationModal
|
||||||
|
title={`Mute @${account.get('acct')}`}
|
||||||
|
message={<FormattedMessage id='confirmations.mute.message' defaultMessage='Are you sure you want to mute @{name}?' values={{ name: account.get('acct') }} />}
|
||||||
|
confirm={<FormattedMessage id='mute' defaultMessage='Mute' />}
|
||||||
|
onConfirm={() => {
|
||||||
|
// dispatch(blockDomain(domain))
|
||||||
|
// dispatch(blockDomain(domain))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import { muteAccount } from '../../actions/accounts'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
||||||
|
cancel: { id: 'confirmation_modal.cancel', defaultMessage: 'Cancel' },
|
||||||
|
confirm: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
|
||||||
|
account: state.getIn(['mutes', 'new', 'account']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
onConfirm(account, notifications) {
|
||||||
|
dispatch(muteAccount(account.get('id'), notifications))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
@injectIntl
|
||||||
|
class UnfollowModal extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
isSubmitting: PropTypes.bool.isRequired,
|
||||||
|
account: PropTypes.object.isRequired,
|
||||||
|
onConfirm: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.button.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
this.props.onConfirm(this.props.account, this.props.notifications)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCancel = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { account, intl } = this.props
|
||||||
|
|
||||||
|
// , {
|
||||||
|
// message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
||||||
|
// confirm: intl.formatMessage(messages.unfollowConfirm),
|
||||||
|
// onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
|
||||||
|
// }));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmationModal
|
||||||
|
title={`Mute @${account.get('acct')}`}
|
||||||
|
message={<FormattedMessage id='confirmations.mute.message' defaultMessage='Are you sure you want to mute @{name}?' values={{ name: account.get('acct') }} />}
|
||||||
|
confirm={<FormattedMessage id='mute' defaultMessage='Mute' />}
|
||||||
|
onConfirm={() => {
|
||||||
|
// dispatch(blockDomain(domain))
|
||||||
|
// dispatch(blockDomain(domain))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import Button from '../button'
|
||||||
|
import Text from '../text'
|
||||||
|
import ModalLayout from './modal_layout'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: { id: 'promo.gab_pro', defaultMessage: 'Upgrade to GabPRO' },
|
||||||
|
text: { id: 'pro_upgrade_modal.text', defaultMessage: 'Gab is fully funded by people like you. Please consider supporting us on our mission to defend free expression online for all people.' },
|
||||||
|
benefits: { id: 'pro_upgrade_modal.benefits', defaultMessage: 'Here are just some of the benefits that thousands of GabPRO members receive:' },
|
||||||
|
})
|
||||||
|
|
||||||
|
export default
|
||||||
|
@injectIntl
|
||||||
|
class HomeTimelineSettingsModal extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { intl } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Text>
|
||||||
|
{intl.formatMessage(messages.text)}
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
{intl.formatMessage(messages.benefits)}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<div className={[_s.default, _s.my10].join(' ')}>
|
||||||
|
<Text>• Schedule Posts</Text>
|
||||||
|
<Text>• Get Verified</Text>
|
||||||
|
<Text>• Create Groups</Text>
|
||||||
|
<Text>• Larger Video and Image Uploads</Text>
|
||||||
|
<Text>• Receive the PRO Badge</Text>
|
||||||
|
<Text>• Remove in-feed promotions</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
centered
|
||||||
|
backgroundColor='brand'
|
||||||
|
color='white'
|
||||||
|
icon='pro'
|
||||||
|
href='https://pro.gab.com'
|
||||||
|
className={_s.justifyContentCenter}
|
||||||
|
iconClassName={[_s.mr5, _s.fillColorWhite].join(' ')}
|
||||||
|
>
|
||||||
|
<Text color='inherit' weight='bold' align='center'>
|
||||||
|
{intl.formatMessage(messages.title)}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,73 +1,119 @@
|
|||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { FormattedMessage } from 'react-intl';
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import Video from '../../features/video';
|
import { closeModal } from '../../actions/modal'
|
||||||
|
import { changeSetting, saveSettings } from '../../actions/settings'
|
||||||
|
import ModalLayout from './modal_layout'
|
||||||
|
import Button from '../button'
|
||||||
|
import SettingSwitch from '../setting_switch'
|
||||||
|
import Text from '../text'
|
||||||
|
|
||||||
export const previewState = 'previewVideoModal';
|
const messages = defineMessages({
|
||||||
|
title: { id: 'home_timeline_settings', defaultMessage: 'Home Timeline Settings' },
|
||||||
|
saveAndClose: { id: 'saveClose', defaultMessage: 'Save & Close' },
|
||||||
|
showVideos: { id: 'home.column_settings.show_videos', defaultMessage: 'Show videos' },
|
||||||
|
showPhotos: { id: 'home.column_settings.show_photos', defaultMessage: 'Show photos' },
|
||||||
|
showPolls: { id: 'home.column_settings.show_polls', defaultMessage: 'Show polls' },
|
||||||
|
showReposts: { id: 'home.column_settings.show_reposts', defaultMessage: 'Show comments' },
|
||||||
|
showReplies: { id: 'home.column_settings.show_replies', defaultMessage: 'Show replies' },
|
||||||
|
})
|
||||||
|
|
||||||
export default class VideoModal extends ImmutablePureComponent {
|
const mapStateToProps = state => ({
|
||||||
|
settings: state.getIn(['settings', 'home']),
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
onChange(key, checked) {
|
||||||
|
dispatch(changeSetting(['home', ...key], checked))
|
||||||
|
},
|
||||||
|
onSave() {
|
||||||
|
dispatch(saveSettings())
|
||||||
|
dispatch(closeModal())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
@injectIntl
|
||||||
|
class HomeTimelineSettingsModal extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
media: ImmutablePropTypes.map.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
status: ImmutablePropTypes.map,
|
settings: ImmutablePropTypes.map.isRequired,
|
||||||
time: PropTypes.number,
|
onChange: PropTypes.func.isRequired,
|
||||||
onClose: PropTypes.func.isRequired,
|
onSave: PropTypes.func.isRequired,
|
||||||
};
|
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
router: PropTypes.object,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
if (this.context.router) {
|
|
||||||
const history = this.context.router.history;
|
|
||||||
|
|
||||||
history.push(history.location.pathname, previewState);
|
|
||||||
|
|
||||||
this.unlistenHistory = history.listen(() => {
|
|
||||||
this.props.onClose();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount () {
|
handleSaveAndClose = () => {
|
||||||
if (this.context.router) {
|
this.props.onSave()
|
||||||
this.unlistenHistory();
|
|
||||||
|
|
||||||
if (this.context.router.history.location.state === previewState) {
|
|
||||||
this.context.router.history.goBack();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleStatusClick = e => {
|
render() {
|
||||||
if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
const { intl, settings, onChange } = this.props
|
||||||
e.preventDefault();
|
|
||||||
this.context.router.history.push(`/${this.props.status.getIn(['account', 'acct'])}/posts/${this.props.status.get('id')}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { media, status, time, onClose } = this.props;
|
|
||||||
|
|
||||||
const link = status && <a href={status.get('url')} onClick={this.handleStatusClick}><FormattedMessage id='lightbox.view_context' defaultMessage='View context' /></a>;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='modal-root__modal video-modal'>
|
<ModalLayout
|
||||||
<div>
|
width='320'
|
||||||
<Video
|
title={intl.formatMessage(messages.title)}
|
||||||
preview={media.get('preview_url')}
|
>
|
||||||
blurhash={media.get('blurhash')}
|
|
||||||
src={media.get('url')}
|
<div className={[_s.default, _s.my10, _s.pb10].join(' ')}>
|
||||||
startTime={time}
|
<SettingSwitch
|
||||||
onCloseVideo={onClose}
|
prefix='home_timeline'
|
||||||
link={link}
|
settings={settings}
|
||||||
detailed
|
settingPath={['shows', 'polls']}
|
||||||
alt={media.get('description')}
|
onChange={onChange}
|
||||||
|
label={intl.formatMessage(messages.showPolls)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SettingSwitch
|
||||||
|
prefix='home_timeline'
|
||||||
|
settings={settings}
|
||||||
|
settingPath={['shows', 'photos']}
|
||||||
|
onChange={onChange}
|
||||||
|
label={intl.formatMessage(messages.showPhotos)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SettingSwitch
|
||||||
|
prefix='home_timeline'
|
||||||
|
settings={settings}
|
||||||
|
settingPath={['shows', 'videos']}
|
||||||
|
onChange={onChange}
|
||||||
|
label={intl.formatMessage(messages.showVideos)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SettingSwitch
|
||||||
|
prefix='home_timeline'
|
||||||
|
settings={settings}
|
||||||
|
settingPath={['shows', 'repost']}
|
||||||
|
onChange={onChange}
|
||||||
|
label={intl.formatMessage(messages.showReposts)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SettingSwitch
|
||||||
|
prefix='home_timeline'
|
||||||
|
settings={settings}
|
||||||
|
settingPath={['shows', 'reply']}
|
||||||
|
onChange={onChange}
|
||||||
|
label={intl.formatMessage(messages.showReplies)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
<Button
|
||||||
|
centered
|
||||||
|
backgroundColor='brand'
|
||||||
|
color='white'
|
||||||
|
className={_s.justifyContentCenter}
|
||||||
|
onClick={this.handleSaveAndClose}
|
||||||
|
>
|
||||||
|
<Text color='inherit' weight='bold' align='center'>
|
||||||
|
{intl.formatMessage(messages.saveAndClose)}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
</ModalLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,72 @@
|
|||||||
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import { muteAccount } from '../../actions/accounts'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
||||||
|
cancel: { id: 'confirmation_modal.cancel', defaultMessage: 'Cancel' },
|
||||||
|
confirm: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
|
||||||
|
account: state.getIn(['mutes', 'new', 'account']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
onConfirm(account, notifications) {
|
||||||
|
dispatch(muteAccount(account.get('id'), notifications))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
@injectIntl
|
||||||
|
class UnfollowModal extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
isSubmitting: PropTypes.bool.isRequired,
|
||||||
|
account: PropTypes.object.isRequired,
|
||||||
|
onConfirm: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.button.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
this.props.onConfirm(this.props.account, this.props.notifications)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCancel = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { account, intl } = this.props
|
||||||
|
|
||||||
|
// , {
|
||||||
|
// message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
||||||
|
// confirm: intl.formatMessage(messages.unfollowConfirm),
|
||||||
|
// onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
|
||||||
|
// }));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmationModal
|
||||||
|
title={`Mute @${account.get('acct')}`}
|
||||||
|
message={<FormattedMessage id='confirmations.mute.message' defaultMessage='Are you sure you want to mute @{name}?' values={{ name: account.get('acct') }} />}
|
||||||
|
confirm={<FormattedMessage id='mute' defaultMessage='Mute' />}
|
||||||
|
onConfirm={() => {
|
||||||
|
// dispatch(blockDomain(domain))
|
||||||
|
// dispatch(blockDomain(domain))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import { muteAccount } from '../../actions/accounts'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
||||||
|
cancel: { id: 'confirmation_modal.cancel', defaultMessage: 'Cancel' },
|
||||||
|
confirm: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
|
||||||
|
account: state.getIn(['mutes', 'new', 'account']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
onConfirm(account, notifications) {
|
||||||
|
dispatch(muteAccount(account.get('id'), notifications))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
@injectIntl
|
||||||
|
class UnfollowModal extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
isSubmitting: PropTypes.bool.isRequired,
|
||||||
|
account: PropTypes.object.isRequired,
|
||||||
|
onConfirm: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.button.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
this.props.onConfirm(this.props.account, this.props.notifications)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCancel = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { account, intl } = this.props
|
||||||
|
|
||||||
|
// , {
|
||||||
|
// message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
||||||
|
// confirm: intl.formatMessage(messages.unfollowConfirm),
|
||||||
|
// onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
|
||||||
|
// }));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmationModal
|
||||||
|
title={`Mute @${account.get('acct')}`}
|
||||||
|
message={<FormattedMessage id='confirmations.mute.message' defaultMessage='Are you sure you want to mute @{name}?' values={{ name: account.get('acct') }} />}
|
||||||
|
confirm={<FormattedMessage id='mute' defaultMessage='Mute' />}
|
||||||
|
onConfirm={() => {
|
||||||
|
// dispatch(blockDomain(domain))
|
||||||
|
// dispatch(blockDomain(domain))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,8 +1,11 @@
|
|||||||
import { defineMessages, injectIntl } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
|
import classNames from 'classnames/bind'
|
||||||
import Button from '../button'
|
import Button from '../button'
|
||||||
import Block from '../block'
|
import Block from '../block'
|
||||||
import Heading from '../heading'
|
import Heading from '../heading'
|
||||||
|
|
||||||
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||||
})
|
})
|
||||||
@ -14,6 +17,13 @@ class ModalLayout extends PureComponent {
|
|||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
|
width: PropTypes.number,
|
||||||
|
hideClose: PropTypes.bool,
|
||||||
|
noPadding: PropTypes.bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
width: 600,
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -22,15 +32,26 @@ class ModalLayout extends PureComponent {
|
|||||||
children,
|
children,
|
||||||
intl,
|
intl,
|
||||||
onClose,
|
onClose,
|
||||||
|
width,
|
||||||
|
hideClose,
|
||||||
|
noPadding
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
|
const childrenContainerClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
px15: !noPadding,
|
||||||
|
py10: !noPadding,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.width645PX].join(' ')}>
|
<div style={{width: `${width}px`}}>
|
||||||
<Block>
|
<Block>
|
||||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.borderBottom1PX, _s.borderColorSecondary, _s.height53PX, _s.px15].join(' ')}>
|
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.borderBottom1PX, _s.borderColorSecondary, _s.height53PX, _s.px15].join(' ')}>
|
||||||
<Heading size='h3'>
|
<Heading size='h3'>
|
||||||
{title}
|
{title}
|
||||||
</Heading>
|
</Heading>
|
||||||
|
{
|
||||||
|
!hideClose &&
|
||||||
<Button
|
<Button
|
||||||
backgroundColor='none'
|
backgroundColor='none'
|
||||||
title={intl.formatMessage(messages.close)}
|
title={intl.formatMessage(messages.close)}
|
||||||
@ -40,8 +61,9 @@ class ModalLayout extends PureComponent {
|
|||||||
iconWidth='10px'
|
iconWidth='10px'
|
||||||
iconWidth='10px'
|
iconWidth='10px'
|
||||||
/>
|
/>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div className={[_s.default, _s.px15, _s.py10].join(' ')}>
|
<div className={childrenContainerClasses}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</Block>
|
</Block>
|
||||||
|
@ -9,37 +9,51 @@ import {
|
|||||||
// ListAdder,
|
// ListAdder,
|
||||||
StatusRevisionModal,
|
StatusRevisionModal,
|
||||||
} from '../../features/ui/util/async-components'
|
} from '../../features/ui/util/async-components'
|
||||||
|
|
||||||
import ModalBase from './modal_base'
|
import ModalBase from './modal_base'
|
||||||
import BundleModalError from '../bundle_modal_error'
|
import BundleModalError from '../bundle_modal_error'
|
||||||
|
|
||||||
import ActionsModal from './actions_modal'
|
import ActionsModal from './actions_modal'
|
||||||
import MediaModal from './media_modal'
|
import BlockAccountModal from './block_account_modal'
|
||||||
import VideoModal from './video_modal'
|
import BlockDomainModal from './block_domain_modal'
|
||||||
import BoostModal from './boost_modal'
|
import BoostModal from './boost_modal'
|
||||||
import ConfirmationModal from './confirmation_modal'
|
|
||||||
import HotkeysModal from './hotkeys_modal'
|
|
||||||
import ComposeModal from './compose_modal'
|
import ComposeModal from './compose_modal'
|
||||||
import UnauthorizedModal from './unauthorized_modal'
|
import ConfirmationModal from './confirmation_modal'
|
||||||
import ProUpgradeModal from './pro_upgrade_modal'
|
import GroupAdderModal from './group_adder_modal'
|
||||||
|
import GroupEditorModal from './group_editor_modal'
|
||||||
|
import HomeTimelineSettingsModal from './home_timeline_settings_modal'
|
||||||
|
import HotkeysModal from './hotkeys_modal'
|
||||||
|
import ListAdderModal from './list_adder_modal'
|
||||||
|
import ListEditorModal from './list_editor_modal'
|
||||||
|
import MediaModal from './media_modal'
|
||||||
import ModalLoading from './modal_loading'
|
import ModalLoading from './modal_loading'
|
||||||
|
import ProUpgradeModal from './pro_upgrade_modal'
|
||||||
|
import VideoModal from './video_modal'
|
||||||
|
import UnauthorizedModal from './unauthorized_modal'
|
||||||
|
import UnfollowModal from './unfollow_modal'
|
||||||
|
|
||||||
const MODAL_COMPONENTS = {
|
const MODAL_COMPONENTS = {
|
||||||
'ACTIONS': () => Promise.resolve({ default: ActionsModal }),
|
ACTIONS: () => Promise.resolve({ default: ActionsModal }),
|
||||||
'BOOST': () => Promise.resolve({ default: BoostModal }),
|
BLOCK_ACCOUNT: () => Promise.resolve({ default: BlockAccountModal }),
|
||||||
'COMPOSE': () => Promise.resolve({ default: ComposeModal }),
|
BLOCK_DOMAIN: () => Promise.resolve({ default: BlockDomainModal }),
|
||||||
'CONFIRM': () => Promise.resolve({ default: ConfirmationModal }),
|
BOOST: () => Promise.resolve({ default: BoostModal }),
|
||||||
'EMBED': EmbedModal,
|
COMPOSE: () => Promise.resolve({ default: ComposeModal }),
|
||||||
'HOTKEYS': () => Promise.resolve({ default: HotkeysModal }),
|
CONFIRM: () => Promise.resolve({ default: ConfirmationModal }),
|
||||||
'MEDIA': () => Promise.resolve({ default: MediaModal }),
|
EMBED: () => Promise.resolve({ default: EmbedModal }),
|
||||||
|
GROUP_EDITOR: () => Promise.resolve({ default: GroupEditorModal }),
|
||||||
|
GROUP_ADDER: () => Promise.resolve({ default: GroupAdderModal }),
|
||||||
|
HOME_TIMELINE_SETTINGS: () => Promise.resolve({ default: HomeTimelineSettingsModal }),
|
||||||
|
HOTKEYS: () => Promise.resolve({ default: HotkeysModal }),
|
||||||
|
LIST_EDITOR: () => Promise.resolve({ default: ListEditorModal }),
|
||||||
|
LIST_ADDER: () => Promise.resolve({ default: ListAdderModal }),
|
||||||
|
MEDIA: () => Promise.resolve({ default: MediaModal }),
|
||||||
'MUTE': MuteModal,
|
'MUTE': MuteModal,
|
||||||
'PRO_UPGRADE': () => Promise.resolve({ default: ProUpgradeModal }),
|
PRO_UPGRADE: () => Promise.resolve({ default: ProUpgradeModal }),
|
||||||
'REPORT': ReportModal,
|
REPORT: ReportModal,
|
||||||
'STATUS_REVISION': StatusRevisionModal,
|
STATUS_REVISION: () => Promise.resolve({ default: StatusRevisionModal }),
|
||||||
'UNAUTHORIZED': () => Promise.resolve({ default: UnauthorizedModal }),
|
UNAUTHORIZED: () => Promise.resolve({ default: UnauthorizedModal }),
|
||||||
'VIDEO': () => Promise.resolve({ default: VideoModal }),
|
UNFOLLOW: () => Promise.resolve({ default: UnfollowModal }),
|
||||||
// 'LIST_EDITOR': ListEditor,
|
VIDEO: () => Promise.resolve({ default: VideoModal }),
|
||||||
// 'LIST_ADDER': ListAdder,
|
|
||||||
// group create
|
|
||||||
// group members
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
@ -48,7 +62,7 @@ const mapStateToProps = state => ({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
onClose (optionalType) {
|
onClose(optionalType) {
|
||||||
if (optionalType === 'COMPOSE') {
|
if (optionalType === 'COMPOSE') {
|
||||||
dispatch(cancelReplyCompose())
|
dispatch(cancelReplyCompose())
|
||||||
}
|
}
|
||||||
@ -67,11 +81,11 @@ class ModalRoot extends PureComponent {
|
|||||||
onClose: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
getSnapshotBeforeUpdate () {
|
getSnapshotBeforeUpdate() {
|
||||||
return { visible: !!this.props.type }
|
return { visible: !!this.props.type }
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate (prevProps, prevState, { visible }) {
|
componentDidUpdate(prevProps, prevState, { visible }) {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
document.body.classList.add('with-modals--active')
|
document.body.classList.add('with-modals--active')
|
||||||
} else {
|
} else {
|
||||||
@ -92,7 +106,7 @@ class ModalRoot extends PureComponent {
|
|||||||
onClose(type)
|
onClose(type)
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render() {
|
||||||
const { type, props } = this.props
|
const { type, props } = this.props
|
||||||
const visible = !!type
|
const visible = !!type
|
||||||
|
|
||||||
|
@ -1,40 +1,34 @@
|
|||||||
import { injectIntl, defineMessages } from 'react-intl';
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
import { closeModal } from '../../actions/modal';
|
import { makeGetAccount } from '../../selectors'
|
||||||
import { muteAccount } from '../../actions/accounts';
|
import { closeModal } from '../../actions/modal'
|
||||||
import { toggleHideNotifications } from '../../actions/mutes';
|
import { muteAccount } from '../../actions/accounts'
|
||||||
import ToggleSwitch from '../toggle_switch';
|
import ConfirmationModal from './confirmation_modal'
|
||||||
import Button from '../button';
|
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
title: { id: 'mute_title', defaultMessage: 'Mute {name}' },
|
||||||
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
||||||
hideNotifications: { id: 'mute_modal.hide_notifications', defaultMessage: 'Hide notifications from this user?' },
|
mute: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' },
|
||||||
cancel: { id: 'confirmation_modal.cancel', defaultMessage: 'Cancel' },
|
})
|
||||||
confirm: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' },
|
|
||||||
});
|
const mapStateToProps = (state, { accountId }) => {
|
||||||
|
const getAccount = makeGetAccount()
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
|
||||||
return {
|
return {
|
||||||
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
|
account: getAccount(state, accountId),
|
||||||
account: state.getIn(['mutes', 'new', 'account']),
|
}
|
||||||
notifications: state.getIn(['mutes', 'new', 'notifications']),
|
}
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = dispatch => {
|
||||||
return {
|
return {
|
||||||
onConfirm(account, notifications) {
|
onConfirm(account, notifications) {
|
||||||
dispatch(muteAccount(account.get('id'), notifications));
|
dispatch(closeModal())
|
||||||
|
dispatch(muteAccount(account.get('id'), notifications))
|
||||||
},
|
},
|
||||||
|
|
||||||
onClose() {
|
onClose() {
|
||||||
dispatch(closeModal());
|
dispatch(closeModal())
|
||||||
},
|
},
|
||||||
|
}
|
||||||
onToggleNotifications() {
|
}
|
||||||
dispatch(toggleHideNotifications());
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@connect(mapStateToProps, mapDispatchToProps)
|
@connect(mapStateToProps, mapDispatchToProps)
|
||||||
@ -42,64 +36,39 @@ export default
|
|||||||
class MuteModal extends PureComponent {
|
class MuteModal extends PureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
isSubmitting: PropTypes.bool.isRequired,
|
|
||||||
account: PropTypes.object.isRequired,
|
account: PropTypes.object.isRequired,
|
||||||
notifications: PropTypes.bool.isRequired,
|
|
||||||
onClose: PropTypes.func.isRequired,
|
|
||||||
onConfirm: PropTypes.func.isRequired,
|
onConfirm: PropTypes.func.isRequired,
|
||||||
onToggleNotifications: PropTypes.func.isRequired,
|
onClose: PropTypes.func.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
this.button.focus();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick = () => {
|
handleClick = () => {
|
||||||
this.props.onClose();
|
this.props.onConfirm(this.props.account)
|
||||||
this.props.onConfirm(this.props.account, this.props.notifications);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCancel = () => {
|
handleClose = () => {
|
||||||
this.props.onClose();
|
this.props.onClose()
|
||||||
}
|
}
|
||||||
|
|
||||||
setRef = (c) => {
|
render() {
|
||||||
this.button = c;
|
const { account, intl } = this.props
|
||||||
}
|
|
||||||
|
|
||||||
toggleNotifications = () => {
|
const title = intl.formatMessage(messages.title, {
|
||||||
this.props.onToggleNotifications();
|
name: !!account ? account.get('acct') : '',
|
||||||
}
|
})
|
||||||
|
const message = intl.formatMessage(messages.muteMessage, {
|
||||||
render () {
|
name: !!account ? account.get('acct') : '',
|
||||||
const { account, notifications, intl } = this.props;
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='modal-root__modal mute-modal'>
|
<ConfirmationModal
|
||||||
<div className='mute-modal__container'>
|
title={title}
|
||||||
<p>
|
message={message}
|
||||||
{intl.formatMessage(messages.muteMessage, { name: <strong>@{account.get('acct')}</strong> })}
|
confirm={intl.formatMessage(messages.mute)}
|
||||||
</p>
|
onClose={this.handleClose}
|
||||||
<div>
|
onConfirm={this.handleClick}
|
||||||
<label htmlFor='mute-modal__hide-notifications-checkbox'>
|
/>
|
||||||
{intl.formatMessage(messages.hideNotifications)}
|
)
|
||||||
{' '}
|
|
||||||
<ToggleSwitch id='mute-modal__hide-notifications-checkbox' checked={notifications} onChange={this.toggleNotifications} />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='mute-modal__action-bar'>
|
|
||||||
<Button onClick={this.handleCancel} className='mute-modal__cancel-button'>
|
|
||||||
{intl.formatMessage(messages.cancel)}
|
|
||||||
</Button>
|
|
||||||
<Button onClick={this.handleClick} ref={this.setRef}>
|
|
||||||
{intl.formatMessage(messages.confirm)}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,59 @@
|
|||||||
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import Button from '../button'
|
||||||
|
import Text from '../text'
|
||||||
|
import ModalLayout from './modal_layout'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: { id: 'promo.gab_pro', defaultMessage: 'Upgrade to GabPRO' },
|
||||||
|
text: { id: 'pro_upgrade_modal.text', defaultMessage: 'Gab is fully funded by people like you. Please consider supporting us on our mission to defend free expression online for all people.' },
|
||||||
|
benefits: { id: 'pro_upgrade_modal.benefits', defaultMessage: 'Here are just some of the benefits that thousands of GabPRO members receive:' },
|
||||||
|
})
|
||||||
|
|
||||||
|
export default
|
||||||
|
@injectIntl
|
||||||
|
class HomeTimelineSettingsModal extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { intl } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Text>
|
||||||
|
{intl.formatMessage(messages.text)}
|
||||||
|
</Text>
|
||||||
|
<Text>
|
||||||
|
{intl.formatMessage(messages.benefits)}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<div className={[_s.default, _s.my10].join(' ')}>
|
||||||
|
<Text>• Schedule Posts</Text>
|
||||||
|
<Text>• Get Verified</Text>
|
||||||
|
<Text>• Create Groups</Text>
|
||||||
|
<Text>• Larger Video and Image Uploads</Text>
|
||||||
|
<Text>• Receive the PRO Badge</Text>
|
||||||
|
<Text>• Remove in-feed promotions</Text>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
centered
|
||||||
|
backgroundColor='brand'
|
||||||
|
color='white'
|
||||||
|
icon='pro'
|
||||||
|
href='https://pro.gab.com'
|
||||||
|
className={_s.justifyContentCenter}
|
||||||
|
iconClassName={[_s.mr5, _s.fillColorWhite].join(' ')}
|
||||||
|
>
|
||||||
|
<Text color='inherit' weight='bold' align='center'>
|
||||||
|
{intl.formatMessage(messages.title)}
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,16 @@
|
|||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { OrderedSet } from 'immutable'
|
||||||
import { OrderedSet } from 'immutable';
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import { changeReportComment, changeReportForward, submitReport } from '../../actions/reports';
|
import { changeReportComment, changeReportForward, submitReport } from '../../actions/reports'
|
||||||
import { expandAccountTimeline } from '../../actions/timelines';
|
import { expandAccountTimeline } from '../../actions/timelines'
|
||||||
import { makeGetAccount } from '../../selectors';
|
import { makeGetAccount } from '../../selectors'
|
||||||
import StatusCheckBox from '../status_check_box';
|
import ModalLayout from './modal_layout'
|
||||||
import ToggleSwitch from '../toggle_switch';
|
import Button from '../button'
|
||||||
import Button from '../button';
|
import StatusCheckBox from '../status_check_box'
|
||||||
import IconButton from '../icon_button';
|
import Switch from '../switch'
|
||||||
|
import Text from '../Text'
|
||||||
|
import Textarea from '../Textarea'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
close: { id: 'lightbox.close', defaultMessage: 'Close' },
|
||||||
@ -82,29 +84,36 @@ class ReportModal extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { account, comment, intl, statusIds, isSubmitting, forward, onClose } = this.props;
|
const {
|
||||||
|
account,
|
||||||
|
comment,
|
||||||
|
intl,
|
||||||
|
statusIds,
|
||||||
|
isSubmitting,
|
||||||
|
forward,
|
||||||
|
onClose
|
||||||
|
} = this.props
|
||||||
|
|
||||||
if (!account) {
|
if (!account) return null
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const domain = account.get('acct').split('@')[1];
|
const domain = account.get('acct').split('@')[1];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='modal-root__modal report-modal'>
|
<ModalLayout
|
||||||
<div className='report-modal__target'>
|
noPadding
|
||||||
<IconButton className='media-modal__close' title={intl.formatMessage(messages.close)} icon='times' onClick={onClose} size={16} />
|
title={intl.formatMessage(messages.target, {
|
||||||
{intl.formatMessage(messages.target, {
|
target: account.get('acct')
|
||||||
target: <strong>{account.get('acct')}</strong>
|
|
||||||
})}
|
})}
|
||||||
</div>
|
>
|
||||||
|
|
||||||
<div className='report-modal__container'>
|
<div className={[_s.default, _s.flexRow].join(' ')}>
|
||||||
<div className='report-modal__comment'>
|
<div className={[_s.default, _s.width50PC, _s.py10, _s.px15, _s.borderRight1PX, _s.borderColorSecondary].join(' ')}>
|
||||||
<p>{intl.formatMessage(messages.hint)}</p>
|
<Text color='secondary' size='small'>
|
||||||
|
{intl.formatMessage(messages.hint)}
|
||||||
|
</Text>
|
||||||
|
|
||||||
<textarea
|
<div className={_s.my10}>
|
||||||
className='setting-text light'
|
<Textarea
|
||||||
placeholder={intl.formatMessage(messages.placeholder)}
|
placeholder={intl.formatMessage(messages.placeholder)}
|
||||||
value={comment}
|
value={comment}
|
||||||
onChange={this.handleCommentChange}
|
onChange={this.handleCommentChange}
|
||||||
@ -112,32 +121,53 @@ class ReportModal extends ImmutablePureComponent {
|
|||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
{domain && (
|
{
|
||||||
|
domain &&
|
||||||
<div>
|
<div>
|
||||||
<p>{intl.formatMessage(messages.forwardHint)}</p>
|
<Text color='secondary' size='small'>
|
||||||
|
{intl.formatMessage(messages.forwardHint)}
|
||||||
|
</Text>
|
||||||
|
|
||||||
<div className='setting-toggle'>
|
<div className='setting-toggle'>
|
||||||
<ToggleSwitch id='report-forward' checked={forward} disabled={isSubmitting} onChange={this.handleForwardChange} />
|
<Switch
|
||||||
<label htmlFor='report-forward' className='setting-toggle__label'>
|
id='report-forward'
|
||||||
{intl.formatMessage(messages.forward, {
|
checked={forward}
|
||||||
target: domain
|
disabled={isSubmitting}
|
||||||
|
onChange={this.handleForwardChange}
|
||||||
|
label={intl.formatMessage(messages.forward, {
|
||||||
|
target: domain,
|
||||||
})}
|
})}
|
||||||
</label>
|
labelProps={{
|
||||||
|
size: 'small',
|
||||||
|
color: 'secondary',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
}
|
||||||
|
|
||||||
<Button disabled={isSubmitting} text={intl.formatMessage(messages.submit)} onClick={this.handleSubmit} />
|
<Button
|
||||||
|
disabled={isSubmitting}
|
||||||
|
onClick={this.handleSubmit}
|
||||||
|
className={_s.marginTopAuto}
|
||||||
|
>
|
||||||
|
{intl.formatMessage(messages.submit)}
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='report-modal__statuses'>
|
<div className={[_s.default, _s.width50PC].join(' ')}>
|
||||||
<div>
|
<div className={[_s.default, _s.heightMax80VH, _s.overflowYScroll, _s.pr15, _s.py10].join(' ')}>
|
||||||
{statusIds.map(statusId => <StatusCheckBox id={statusId} key={statusId} disabled={isSubmitting} />)}
|
{
|
||||||
</div>
|
statusIds.map(statusId => (
|
||||||
|
<StatusCheckBox id={statusId} key={statusId} disabled={isSubmitting} />
|
||||||
|
))
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</ModalLayout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
72
app/javascript/gabsocial/components/modal/unfollow_modal.js
Normal file
72
app/javascript/gabsocial/components/modal/unfollow_modal.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
|
import { muteAccount } from '../../actions/accounts'
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
muteMessage: { id: 'confirmations.mute.message', defaultMessage: 'Are you sure you want to mute {name}?' },
|
||||||
|
cancel: { id: 'confirmation_modal.cancel', defaultMessage: 'Cancel' },
|
||||||
|
confirm: { id: 'confirmations.mute.confirm', defaultMessage: 'Mute' },
|
||||||
|
})
|
||||||
|
|
||||||
|
const mapStateToProps = state => {
|
||||||
|
return {
|
||||||
|
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
|
||||||
|
account: state.getIn(['mutes', 'new', 'account']),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = dispatch => {
|
||||||
|
return {
|
||||||
|
onConfirm(account, notifications) {
|
||||||
|
dispatch(muteAccount(account.get('id'), notifications))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
@injectIntl
|
||||||
|
class UnfollowModal extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
isSubmitting: PropTypes.bool.isRequired,
|
||||||
|
account: PropTypes.object.isRequired,
|
||||||
|
onConfirm: PropTypes.func.isRequired,
|
||||||
|
intl: PropTypes.object.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.button.focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
handleClick = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
this.props.onConfirm(this.props.account, this.props.notifications)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleCancel = () => {
|
||||||
|
this.props.onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { account, intl } = this.props
|
||||||
|
|
||||||
|
// , {
|
||||||
|
// message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
||||||
|
// confirm: intl.formatMessage(messages.unfollowConfirm),
|
||||||
|
// onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
|
||||||
|
// }));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmationModal
|
||||||
|
title={`Mute @${account.get('acct')}`}
|
||||||
|
message={<FormattedMessage id='confirmations.mute.message' defaultMessage='Are you sure you want to mute @{name}?' values={{ name: account.get('acct') }} />}
|
||||||
|
confirm={<FormattedMessage id='mute' defaultMessage='Mute' />}
|
||||||
|
onConfirm={() => {
|
||||||
|
// dispatch(blockDomain(domain))
|
||||||
|
// dispatch(blockDomain(domain))
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -28,7 +28,7 @@ class MediaGalleryPanel extends ImmutablePureComponent {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
accountId: PropTypes.string,
|
accountId: PropTypes.string,
|
||||||
account: ImmutablePropTypes.map.isRequired,
|
account: ImmutablePropTypes.map,
|
||||||
attachments: ImmutablePropTypes.list.isRequired,
|
attachments: ImmutablePropTypes.list.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
@ -54,8 +54,6 @@ class MediaGalleryPanel extends ImmutablePureComponent {
|
|||||||
attachments
|
attachments
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
console.log("account, attachments:", account, attachments)
|
|
||||||
|
|
||||||
if (!account || !attachments) return null
|
if (!account || !attachments) return null
|
||||||
if (attachments.size === 0) return null
|
if (attachments.size === 0) return null
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ class ProfileInfoPanel extends ImmutablePureComponent {
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
identityProofs: ImmutablePropTypes.list,
|
identityProofs: ImmutablePropTypes.list,
|
||||||
account: ImmutablePropTypes.map.isRequired,
|
account: ImmutablePropTypes.map,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,15 +50,15 @@ class ProfileInfoPanel extends ImmutablePureComponent {
|
|||||||
render() {
|
render() {
|
||||||
const { intl, account, identityProofs } = this.props
|
const { intl, account, identityProofs } = this.props
|
||||||
|
|
||||||
const fields = !account ? null : account.get('fields')
|
if (!account) return null
|
||||||
const content = !account ? null : { __html: account.get('note_emojified') }
|
|
||||||
const memberSinceDate = !account ? null : intl.formatDate(account.get('created_at'), { month: 'long', year: 'numeric' })
|
const fields = account.get('fields')
|
||||||
|
const content = { __html: account.get('note_emojified') }
|
||||||
|
const memberSinceDate = intl.formatDate(account.get('created_at'), { month: 'long', year: 'numeric' })
|
||||||
const hasNote = !!content ? (account.get('note').length > 0 && account.get('note') !== '<p></p>') : false
|
const hasNote = !!content ? (account.get('note').length > 0 && account.get('note') !== '<p></p>') : false
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelLayout title={intl.formatMessage(messages.title)}>
|
<PanelLayout title={intl.formatMessage(messages.title)}>
|
||||||
{
|
|
||||||
!!account &&
|
|
||||||
<div className={[_s.default].join(' ')}>
|
<div className={[_s.default].join(' ')}>
|
||||||
{
|
{
|
||||||
hasNote &&
|
hasNote &&
|
||||||
@ -136,7 +136,6 @@ class ProfileInfoPanel extends ImmutablePureComponent {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
}
|
|
||||||
</PanelLayout>
|
</PanelLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ const messages = defineMessages({
|
|||||||
gabs: { id: 'account.gabs', defaultMessage: 'Gabs' },
|
gabs: { id: 'account.gabs', defaultMessage: 'Gabs' },
|
||||||
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
||||||
follows: { id: 'account.follows', defaultMessage: 'Follows' },
|
follows: { id: 'account.follows', defaultMessage: 'Follows' },
|
||||||
favorites: { id: 'navigation_bar.favorites', defaultMessage: 'Favorites' },
|
likes: { id: 'likes', defaultMessage: 'Likes' },
|
||||||
})
|
})
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@ -18,7 +18,7 @@ export default
|
|||||||
class ProfileStatsPanel extends ImmutablePureComponent {
|
class ProfileStatsPanel extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
account: ImmutablePropTypes.list.isRequired,
|
account: ImmutablePropTypes.map,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,9 +50,9 @@ class ProfileStatsPanel extends ImmutablePureComponent {
|
|||||||
{
|
{
|
||||||
account.get('id') === me &&
|
account.get('id') === me &&
|
||||||
<UserStat
|
<UserStat
|
||||||
title={intl.formatMessage(messages.favorites)}
|
title={intl.formatMessage(messages.likes)}
|
||||||
value={shortNumberFormat(favouritesCount)}
|
value={shortNumberFormat(favouritesCount)}
|
||||||
to={`/${account.get('acct')}/favorites`}
|
to={`/${account.get('acct')}/likes`}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,19 +2,24 @@ import { NavLink } from 'react-router-dom'
|
|||||||
import { injectIntl, defineMessages } from 'react-intl'
|
import { injectIntl, defineMessages } from 'react-intl'
|
||||||
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 classNames from 'classnames/bind'
|
||||||
import { me } from '../../initial_state'
|
import { me } from '../../initial_state'
|
||||||
import { makeGetAccount } from '../../selectors'
|
import { makeGetAccount } from '../../selectors'
|
||||||
import { shortNumberFormat } from '../../utils/numbers'
|
import { shortNumberFormat } from '../../utils/numbers'
|
||||||
|
import Button from '../button'
|
||||||
import DisplayName from '../display_name'
|
import DisplayName from '../display_name'
|
||||||
import Avatar from '../avatar'
|
import Avatar from '../avatar'
|
||||||
import Image from '../image'
|
import Image from '../image'
|
||||||
import UserStat from '../user_stat'
|
import UserStat from '../user_stat'
|
||||||
import PanelLayout from './panel_layout'
|
import PanelLayout from './panel_layout'
|
||||||
|
|
||||||
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
gabs: { id: 'account.posts', defaultMessage: 'Gabs' },
|
gabs: { id: 'account.posts', defaultMessage: 'Gabs' },
|
||||||
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
||||||
follows: { id: 'account.follows', defaultMessage: 'Follows' }
|
follows: { id: 'account.follows', defaultMessage: 'Follows' },
|
||||||
|
edit_profile: { id: 'account.edit_profile', defaultMessage: 'Edit profile' },
|
||||||
})
|
})
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
@ -32,15 +37,51 @@ class UserPanel extends ImmutablePureComponent {
|
|||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
hovering: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseEnter = () => {
|
||||||
|
this.setState({ hovering: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMouseLeave = () => {
|
||||||
|
this.setState({ hovering: false })
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { account, intl } = this.props
|
const { account, intl } = this.props
|
||||||
|
const { hovering } = this.state
|
||||||
|
|
||||||
|
const buttonClasses = cx({
|
||||||
|
positionAbsolute: 1,
|
||||||
|
mt10: 1,
|
||||||
|
mr10: 1,
|
||||||
|
top0: 1,
|
||||||
|
right0: 1,
|
||||||
|
displayNone: !hovering,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelLayout noPadding>
|
<PanelLayout noPadding>
|
||||||
|
<div
|
||||||
|
className={[_s.default, _s.height122PX].join(' ')}
|
||||||
|
onMouseEnter={() => this.handleOnMouseEnter()}
|
||||||
|
onMouseLeave={() => this.handleOnMouseLeave()}
|
||||||
|
>
|
||||||
<Image
|
<Image
|
||||||
className={_s.height122PX}
|
className={_s.height122PX}
|
||||||
src={account.get('header_static')}
|
src={account.get('header_static')}
|
||||||
/>
|
/>
|
||||||
|
<Button
|
||||||
|
color='secondary'
|
||||||
|
backgroundColor='secondary'
|
||||||
|
radiusSmall
|
||||||
|
className={buttonClasses}
|
||||||
|
>
|
||||||
|
{intl.formatMessage(messages.edit_profile)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<NavLink
|
<NavLink
|
||||||
className={[_s.default, _s.flexRow, _s.py10, _s.px15, _s.noUnderline].join(' ')}
|
className={[_s.default, _s.flexRow, _s.py10, _s.px15, _s.noUnderline].join(' ')}
|
||||||
|
@ -21,11 +21,11 @@ const mapStateToProps = state => ({
|
|||||||
|
|
||||||
const mapDispatchToProps = (dispatch, { status, items }) => ({
|
const mapDispatchToProps = (dispatch, { status, items }) => ({
|
||||||
onOpen(id, onItemClick, popoverPlacement, keyboard) {
|
onOpen(id, onItemClick, popoverPlacement, keyboard) {
|
||||||
dispatch(isUserTouching() ? openModal('ACTIONS', {
|
// dispatch(isUserTouching() ? openModal('ACTIONS', {
|
||||||
status,
|
// status,
|
||||||
actions: items,
|
// actions: items,
|
||||||
onClick: onItemClick,
|
// onClick: onItemClick,
|
||||||
}) : openPopover(id, popoverPlacement, keyboard))
|
// }) : openPopover(id, popoverPlacement, keyboard))
|
||||||
},
|
},
|
||||||
onClose(id) {
|
onClose(id) {
|
||||||
dispatch(closeModal())
|
dispatch(closeModal())
|
||||||
@ -42,9 +42,6 @@ class PopoverBase extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
icon: PropTypes.string.isRequired,
|
|
||||||
items: PropTypes.array.isRequired,
|
|
||||||
size: PropTypes.number.isRequired,
|
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
status: ImmutablePropTypes.map,
|
status: ImmutablePropTypes.map,
|
||||||
@ -68,28 +65,12 @@ class PopoverBase extends ImmutablePureComponent {
|
|||||||
id: id++,
|
id: id++,
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick = ({ target, type }) => {
|
|
||||||
if (this.state.id === this.props.openPopoverType) {
|
|
||||||
this.handleClose()
|
|
||||||
} else {
|
|
||||||
const { top } = target.getBoundingClientRect()
|
|
||||||
const placement = top * 2 < innerHeight ? 'bottom' : 'top'
|
|
||||||
|
|
||||||
this.props.onOpen(this.state.id, this.handleItemClick, placement, type !== 'click')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handleClose = () => {
|
handleClose = () => {
|
||||||
this.props.onClose(this.state.id)
|
this.props.onClose(this.state.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleKeyDown = e => {
|
handleKeyDown = e => {
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
case ' ':
|
|
||||||
case 'Enter':
|
|
||||||
this.handleClick(e)
|
|
||||||
e.preventDefault()
|
|
||||||
break
|
|
||||||
case 'Escape':
|
case 'Escape':
|
||||||
this.handleClose()
|
this.handleClose()
|
||||||
break
|
break
|
||||||
@ -127,13 +108,8 @@ class PopoverBase extends ImmutablePureComponent {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
icon,
|
|
||||||
children,
|
children,
|
||||||
visible,
|
visible,
|
||||||
items,
|
|
||||||
size,
|
|
||||||
title,
|
|
||||||
disabled,
|
|
||||||
position,
|
position,
|
||||||
openPopoverType,
|
openPopoverType,
|
||||||
targetRef,
|
targetRef,
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
import Block from '../block'
|
import Block from '../block'
|
||||||
|
|
||||||
export default class PopoverLayout extends PureComponent {
|
export default class PopoverLayout extends PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
children: PropTypes.node,
|
||||||
|
className: PropTypes.string,
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children } = this.props
|
const { children, className } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className={className}>
|
||||||
<Block>
|
<Block>
|
||||||
{children}
|
{children}
|
||||||
</Block>
|
</Block>
|
||||||
|
@ -11,7 +11,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
mentionCompose,
|
mentionCompose,
|
||||||
} from '../../actions/compose'
|
} from '../../actions/compose'
|
||||||
import { initMuteModal } from '../../actions/mutes'
|
import { muteAccount } from '../../actions/accounts'
|
||||||
import { initReport } from '../../actions/reports'
|
import { initReport } from '../../actions/reports'
|
||||||
import { openModal } from '../../actions/modal'
|
import { openModal } from '../../actions/modal'
|
||||||
import { blockDomain, unblockDomain } from '../../actions/domain_blocks'
|
import { blockDomain, unblockDomain } from '../../actions/domain_blocks'
|
||||||
@ -23,7 +23,6 @@ import List from '../list'
|
|||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' },
|
unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' },
|
||||||
blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
|
|
||||||
blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' },
|
blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' },
|
||||||
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
|
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
|
||||||
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' },
|
||||||
@ -45,14 +44,12 @@ const messages = defineMessages({
|
|||||||
hideReposts: { id: 'account.hide_reblogs', defaultMessage: 'Hide reposts from @{name}' },
|
hideReposts: { id: 'account.hide_reblogs', defaultMessage: 'Hide reposts from @{name}' },
|
||||||
showReposts: { id: 'account.show_reblogs', defaultMessage: 'Show reposts from @{name}' },
|
showReposts: { id: 'account.show_reblogs', defaultMessage: 'Show reposts from @{name}' },
|
||||||
preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
|
preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
|
||||||
follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
|
|
||||||
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
|
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
|
||||||
domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' },
|
domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' },
|
||||||
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
|
||||||
endorse: { id: 'account.endorse', defaultMessage: 'Feature on profile' },
|
admin_account: { id: 'admin_account', defaultMessage: 'Open moderation interface' },
|
||||||
unendorse: { id: 'account.unendorse', defaultMessage: 'Don\'t feature on profile' },
|
|
||||||
admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' },
|
|
||||||
add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' },
|
add_or_remove_from_list: { id: 'account.add_or_remove_from_list', defaultMessage: 'Add or Remove from lists' },
|
||||||
|
add_or_remove_from_shortcuts: { id: 'account.add_or_remove_from_shortcuts', defaultMessage: 'Add or Remove from shortcuts' },
|
||||||
accountFollowsYou: { id: 'account.follows_you', defaultMessage: 'Follows you' },
|
accountFollowsYou: { id: 'account.follows_you', defaultMessage: 'Follows you' },
|
||||||
accountBlocked: { id: 'account.blocked', defaultMessage: 'Blocked' },
|
accountBlocked: { id: 'account.blocked', defaultMessage: 'Blocked' },
|
||||||
accountMuted: { id: 'account.muted', defaultMessage: 'Muted' },
|
accountMuted: { id: 'account.muted', defaultMessage: 'Muted' },
|
||||||
@ -72,44 +69,35 @@ const makeMapStateToProps = () => {
|
|||||||
|
|
||||||
const mapDispatchToProps = (dispatch, { intl }) => ({
|
const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
|
|
||||||
onFollow (account) {
|
onFollow(account) {
|
||||||
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
|
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
|
||||||
if (unfollowModal) {
|
if (unfollowModal) {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('UNFOLLOW', {
|
||||||
message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
accountId: account.get('id'),
|
||||||
confirm: intl.formatMessage(messages.unfollowConfirm),
|
}))
|
||||||
onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
dispatch(unfollowAccount(account.get('id')));
|
dispatch(unfollowAccount(account.get('id')))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dispatch(followAccount(account.get('id')));
|
dispatch(followAccount(account.get('id')))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onBlock (account) {
|
onBlock(account) {
|
||||||
if (account.getIn(['relationship', 'blocking'])) {
|
if (account.getIn(['relationship', 'blocking'])) {
|
||||||
dispatch(unblockAccount(account.get('id')));
|
dispatch(unblockAccount(account.get('id')));
|
||||||
} else {
|
} else {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('BLOCK_ACCOUNT', {
|
||||||
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
accountId: account.get('id'),
|
||||||
confirm: intl.formatMessage(messages.blockConfirm),
|
|
||||||
onConfirm: () => dispatch(blockAccount(account.get('id'))),
|
|
||||||
secondary: intl.formatMessage(messages.blockAndReport),
|
|
||||||
onSecondary: () => {
|
|
||||||
dispatch(blockAccount(account.get('id')));
|
|
||||||
dispatch(initReport(account));
|
|
||||||
},
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onMention (account, router) {
|
onMention(account) {
|
||||||
dispatch(mentionCompose(account, router));
|
dispatch(mentionCompose(account));
|
||||||
},
|
},
|
||||||
|
|
||||||
onRepostToggle (account) {
|
onRepostToggle(account) {
|
||||||
if (account.getIn(['relationship', 'showing_reblogs'])) {
|
if (account.getIn(['relationship', 'showing_reblogs'])) {
|
||||||
dispatch(followAccount(account.get('id'), false));
|
dispatch(followAccount(account.get('id'), false));
|
||||||
} else {
|
} else {
|
||||||
@ -117,39 +105,31 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onEndorseToggle (account) {
|
onReport(account) {
|
||||||
if (account.getIn(['relationship', 'endorsed'])) {
|
|
||||||
dispatch(unpinAccount(account.get('id')));
|
|
||||||
} else {
|
|
||||||
dispatch(pinAccount(account.get('id')));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
onReport (account) {
|
|
||||||
dispatch(initReport(account));
|
dispatch(initReport(account));
|
||||||
},
|
},
|
||||||
|
|
||||||
onMute (account) {
|
onMute(account) {
|
||||||
if (account.getIn(['relationship', 'muting'])) {
|
if (account.getIn(['relationship', 'muting'])) {
|
||||||
dispatch(unmuteAccount(account.get('id')));
|
dispatch(unmuteAccount(account.get('id')));
|
||||||
} else {
|
} else {
|
||||||
dispatch(initMuteModal(account));
|
dispatch(openModal('MUTE', {
|
||||||
|
accountId: account.get('id'),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onBlockDomain (domain) {
|
onBlockDomain(domain) {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('BLOCK_DOMAIN', {
|
||||||
message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.' values={{ domain: <strong>{domain}</strong> }} />,
|
domain,
|
||||||
confirm: intl.formatMessage(messages.blockDomainConfirm),
|
|
||||||
onConfirm: () => dispatch(blockDomain(domain)),
|
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
onUnblockDomain (domain) {
|
onUnblockDomain(domain) {
|
||||||
dispatch(unblockDomain(domain));
|
dispatch(unblockDomain(domain));
|
||||||
},
|
},
|
||||||
|
|
||||||
onAddToList(account){
|
onAddToList(account) {
|
||||||
dispatch(openModal('LIST_ADDER', {
|
dispatch(openModal('LIST_ADDER', {
|
||||||
accountId: account.get('id'),
|
accountId: account.get('id'),
|
||||||
}));
|
}));
|
||||||
@ -168,73 +148,163 @@ class ProfileOptionsPopover extends PureComponent {
|
|||||||
|
|
||||||
let menu = [];
|
let menu = [];
|
||||||
|
|
||||||
if (!account) {
|
if (!account) return menu
|
||||||
return [];
|
if (account.get('id') === me) return menu
|
||||||
}
|
|
||||||
|
|
||||||
if ('share' in navigator) {
|
if ('share' in navigator) {
|
||||||
menu.push({ title: intl.formatMessage(messages.share, { name: account.get('username') }), onClick: this.handleShare });
|
menu.push({
|
||||||
|
hideArrow: true,
|
||||||
|
icon: 'share',
|
||||||
|
title: intl.formatMessage(messages.share, { name: account.get('username') }),
|
||||||
|
onClick: this.handleShare
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account.get('id') === me) {
|
menu.push({
|
||||||
menu.push({ title: intl.formatMessage(messages.edit_profile), href: '/settings/profile' });
|
hideArrow: true,
|
||||||
menu.push({ title: intl.formatMessage(messages.preferences), href: '/settings/preferences' });
|
icon: 'comment',
|
||||||
menu.push({ title: intl.formatMessage(messages.follow_requests), to: '/follow_requests' });
|
title: intl.formatMessage(messages.mention, { name: account.get('acct') }),
|
||||||
menu.push({ title: intl.formatMessage(messages.mutes), to: '/mutes' });
|
onClick: this.handleOnMention
|
||||||
menu.push({ title: intl.formatMessage(messages.blocks), to: '/blocks' });
|
});
|
||||||
menu.push({ title: intl.formatMessage(messages.domain_blocks), to: '/domain_blocks' });
|
|
||||||
} else {
|
|
||||||
menu.push({ title: intl.formatMessage(messages.mention, { name: account.get('acct') }), onClick: this.props.onMention });
|
|
||||||
|
|
||||||
if (account.getIn(['relationship', 'following'])) {
|
if (account.getIn(['relationship', 'following'])) {
|
||||||
if (account.getIn(['relationship', 'showing_reblogs'])) {
|
const showingReblogs = account.getIn(['relationship', 'showing_reblogs'])
|
||||||
menu.push({ title: intl.formatMessage(messages.hideReposts, { name: account.get('username') }), onClick: this.props.onRepostToggle });
|
menu.push({
|
||||||
} else {
|
hideArrow: true,
|
||||||
menu.push({ title: intl.formatMessage(messages.showReposts, { name: account.get('username') }), onClick: this.props.onRepostToggle });
|
icon: 'repost',
|
||||||
|
title: intl.formatMessage(showingReblogs ? messages.hideReposts : messages.showReposts, {
|
||||||
|
name: account.get('username')
|
||||||
|
}),
|
||||||
|
onClick: this.handleRepostToggle,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.push({ title: intl.formatMessage(messages.add_or_remove_from_list), onClick: this.props.onAddToList });
|
const isMuting = account.getIn(['relationship', 'muting'])
|
||||||
menu.push({ title: intl.formatMessage(account.getIn(['relationship', 'endorsed']) ? messages.unendorse : messages.endorse), onClick: this.props.onEndorseToggle });
|
menu.push({
|
||||||
}
|
hideArrow: true,
|
||||||
|
icon: 'audio-mute',
|
||||||
|
title: intl.formatMessage(isMuting ? messages.unmute : messages.mute, {
|
||||||
|
name: account.get('username')
|
||||||
|
}),
|
||||||
|
onClick: this.handleMute,
|
||||||
|
})
|
||||||
|
|
||||||
if (account.getIn(['relationship', 'muting'])) {
|
const isBlocking = account.getIn(['relationship', 'blocking'])
|
||||||
menu.push({ title: intl.formatMessage(messages.unmute, { name: account.get('username') }), onClick: this.props.onMute });
|
menu.push({
|
||||||
} else {
|
hideArrow: true,
|
||||||
menu.push({ title: intl.formatMessage(messages.mute, { name: account.get('username') }), onClick: this.props.onMute });
|
icon: 'block',
|
||||||
}
|
title: intl.formatMessage(isBlocking ? messages.unblock : messages.block, {
|
||||||
|
name: account.get('username')
|
||||||
|
}),
|
||||||
|
onClick: this.handleBlock
|
||||||
|
})
|
||||||
|
|
||||||
if (account.getIn(['relationship', 'blocking'])) {
|
menu.push({
|
||||||
menu.push({ title: intl.formatMessage(messages.unblock, { name: account.get('username') }), onClick: this.props.onBlock });
|
hideArrow: true,
|
||||||
} else {
|
icon: 'report',
|
||||||
menu.push({ title: intl.formatMessage(messages.block, { name: account.get('username') }), onClick: this.props.onBlock });
|
title: intl.formatMessage(messages.report, { name: account.get('username') }),
|
||||||
}
|
onClick: this.handleReport
|
||||||
|
})
|
||||||
menu.push({ title: intl.formatMessage(messages.report, { name: account.get('username') }), onClick: this.props.onReport });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (account.get('acct') !== account.get('username')) {
|
if (account.get('acct') !== account.get('username')) {
|
||||||
const domain = account.get('acct').split('@')[1];
|
const domain = account.get('acct').split('@')[1];
|
||||||
|
|
||||||
if (account.getIn(['relationship', 'domain_blocking'])) {
|
const isBlockingDomain = account.getIn(['relationship', 'domain_blocking'])
|
||||||
menu.push({ title: intl.formatMessage(messages.unblockDomain, { domain }), onClick: this.props.onUnblockDomain });
|
menu.push({
|
||||||
} else {
|
hideArrow: true,
|
||||||
menu.push({ title: intl.formatMessage(messages.blockDomain, { domain }), onClick: this.props.onBlockDomain });
|
icon: 'block',
|
||||||
}
|
title: intl.formatMessage(isBlockingDomain ? messages.unblockDomain : messages.blockDomain, {
|
||||||
|
domain,
|
||||||
|
}),
|
||||||
|
onClick: this.handleUnblockDomain
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account.get('id') !== me && isStaff) {
|
menu.push({
|
||||||
menu.push({ title: intl.formatMessage(messages.admin_account, { name: account.get('username') }), href: `/admin/accounts/${account.get('id')}` });
|
hideArrow: true,
|
||||||
|
icon: 'list',
|
||||||
|
title: intl.formatMessage(messages.add_or_remove_from_list),
|
||||||
|
onClick: this.handleAddToList
|
||||||
|
})
|
||||||
|
|
||||||
|
menu.push({
|
||||||
|
hideArrow: true,
|
||||||
|
icon: 'circle',
|
||||||
|
title: intl.formatMessage(messages.add_or_remove_from_shortcuts),
|
||||||
|
onClick: this.handleAddToShortcuts
|
||||||
|
})
|
||||||
|
|
||||||
|
if (isStaff) {
|
||||||
|
menu.push({
|
||||||
|
hideArrow: true,
|
||||||
|
icon: 'circle',
|
||||||
|
title: intl.formatMessage(messages.admin_account),
|
||||||
|
href: `/admin/accounts/${account.get('id')}`
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
return menu;
|
return menu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleShare = () => {
|
||||||
|
// : todo :
|
||||||
|
}
|
||||||
|
|
||||||
|
handleFollow = () => {
|
||||||
|
this.props.onFollow(this.props.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBlock = () => {
|
||||||
|
this.props.onBlock(this.props.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleOnMention = () => {
|
||||||
|
this.props.onMention(this.props.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleReport = () => {
|
||||||
|
this.props.onReport(this.props.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleRepostToggle = () => {
|
||||||
|
this.props.onRepostToggle(this.props.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMute = () => {
|
||||||
|
this.props.onMute(this.props.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBlockDomain = () => {
|
||||||
|
const domain = this.props.account.get('acct').split('@')[1];
|
||||||
|
|
||||||
|
// : todo : alert
|
||||||
|
if (!domain) return;
|
||||||
|
|
||||||
|
this.props.onBlockDomain(domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleUnblockDomain = () => {
|
||||||
|
const domain = this.props.account.get('acct').split('@')[1];
|
||||||
|
|
||||||
|
// : todo : alert
|
||||||
|
if (!domain) return;
|
||||||
|
|
||||||
|
this.props.onUnblockDomain(domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAddToList = () => {
|
||||||
|
this.props.onAddToList(this.props.account);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAddToShortcuts = () => {
|
||||||
|
// : todo :
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const listItems = this.makeMenu()
|
const listItems = this.makeMenu()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PopoverLayout>
|
<PopoverLayout className={_s.width250PX}>
|
||||||
<List
|
<List
|
||||||
scrollKey='profile_options'
|
scrollKey='profile_options'
|
||||||
items={listItems}
|
items={listItems}
|
||||||
|
@ -4,7 +4,7 @@ import List from '../list'
|
|||||||
export default class SidebarMorePopover extends PureComponent {
|
export default class SidebarMorePopover extends PureComponent {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<PopoverLayout>
|
<PopoverLayout className={_s.width240PX}>
|
||||||
<List
|
<List
|
||||||
scrollKey='profile_options'
|
scrollKey='profile_options'
|
||||||
items={[
|
items={[
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import axios from 'axios'
|
||||||
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, FormattedMessage } from 'react-intl'
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||||
@ -11,7 +12,7 @@ import {
|
|||||||
import { openPopover, closePopover } from '../actions/popover'
|
import { openPopover, closePopover } from '../actions/popover'
|
||||||
import { initReport } from '../actions/reports'
|
import { initReport } from '../actions/reports'
|
||||||
import { openModal } from '../actions/modal'
|
import { openModal } from '../actions/modal'
|
||||||
import { unfollowModal } from '../initial_state'
|
import { unfollowModal, me } from '../initial_state'
|
||||||
import Avatar from './avatar'
|
import Avatar from './avatar'
|
||||||
import Image from './image'
|
import Image from './image'
|
||||||
import Text from './text'
|
import Text from './text'
|
||||||
@ -22,6 +23,10 @@ import TabBar from './tab_bar'
|
|||||||
const cx = classNames.bind(_s)
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
follow: { id: 'follow', defaultMessage: 'Follow' },
|
||||||
|
unfollow: { id: 'unfollow', defaultMessage: 'Unfollow' },
|
||||||
|
requested: { id: 'requested', defaultMessage: 'Requested' },
|
||||||
|
unblock: { id: 'unblock', defaultMessage: 'Unblock' },
|
||||||
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
||||||
follows: { id: 'account.follows', defaultMessage: 'Follows' },
|
follows: { id: 'account.follows', defaultMessage: 'Follows' },
|
||||||
profile: { id: 'account.profile', defaultMessage: 'Profile' },
|
profile: { id: 'account.profile', defaultMessage: 'Profile' },
|
||||||
@ -40,13 +45,11 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||||||
dispatch(openPopover('PROFILE_OPTIONS', props))
|
dispatch(openPopover('PROFILE_OPTIONS', props))
|
||||||
},
|
},
|
||||||
|
|
||||||
onFollow (account) {
|
onFollow(account) {
|
||||||
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
|
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
|
||||||
if (unfollowModal) {
|
if (unfollowModal) {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('UNFOLLOW', {
|
||||||
message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
accountId: account.get('id'),
|
||||||
confirm: intl.formatMessage(messages.unfollowConfirm),
|
|
||||||
onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
|
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
dispatch(unfollowAccount(account.get('id')));
|
dispatch(unfollowAccount(account.get('id')));
|
||||||
@ -56,24 +59,17 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onBlock (account) {
|
onBlock(account) {
|
||||||
if (account.getIn(['relationship', 'blocking'])) {
|
if (account.getIn(['relationship', 'blocking'])) {
|
||||||
dispatch(unblockAccount(account.get('id')));
|
dispatch(unblockAccount(account.get('id')));
|
||||||
} else {
|
} else {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('BLOCK_ACCOUNT', {
|
||||||
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
accountId: account.get('id'),
|
||||||
confirm: intl.formatMessage(messages.blockConfirm),
|
|
||||||
onConfirm: () => dispatch(blockAccount(account.get('id'))),
|
|
||||||
secondary: intl.formatMessage(messages.blockAndReport),
|
|
||||||
onSecondary: () => {
|
|
||||||
dispatch(blockAccount(account.get('id')));
|
|
||||||
dispatch(initReport(account));
|
|
||||||
},
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
onRepostToggle (account) {
|
onRepostToggle(account) {
|
||||||
if (account.getIn(['relationship', 'showing_reblogs'])) {
|
if (account.getIn(['relationship', 'showing_reblogs'])) {
|
||||||
dispatch(followAccount(account.get('id'), false));
|
dispatch(followAccount(account.get('id'), false));
|
||||||
} else {
|
} else {
|
||||||
@ -105,12 +101,16 @@ class ProfileHeader extends ImmutablePureComponent {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
handleStartChat = () => {
|
handleFollow = () => {
|
||||||
|
this.props.onFollow(this.props.account)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleFollow = () => {
|
handleUnrequest = () => {
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBlock = () => {
|
||||||
|
// this.props.onBlock(this.props.account)
|
||||||
}
|
}
|
||||||
|
|
||||||
makeInfo() {
|
makeInfo() {
|
||||||
@ -195,6 +195,37 @@ class ProfileHeader extends ImmutablePureComponent {
|
|||||||
|
|
||||||
const avatarSize = headerMissing ? '75' : '150'
|
const avatarSize = headerMissing ? '75' : '150'
|
||||||
|
|
||||||
|
let buttonText;
|
||||||
|
let buttonOptions;
|
||||||
|
if (!account) {
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (account.get('id') !== me && account.get('relationship', null) !== null) {
|
||||||
|
const following = account.getIn(['relationship', 'following'])
|
||||||
|
const requested = account.getIn(['relationship', 'requested'])
|
||||||
|
const blocking = account.getIn(['relationship', 'blocking'])
|
||||||
|
|
||||||
|
if (requested || blocking) {
|
||||||
|
buttonText = intl.formatMessage(requested ? messages.requested : messages.unblock)
|
||||||
|
buttonOptions = {
|
||||||
|
narrow: true,
|
||||||
|
onClick: requested ? this.handleUnrequest : this.handleBlock,
|
||||||
|
color: 'primary',
|
||||||
|
backgroundColor: 'tertiary',
|
||||||
|
}
|
||||||
|
} else if (!account.get('moved') || following) {
|
||||||
|
buttonOptions = {
|
||||||
|
narrow: true,
|
||||||
|
outline: !following,
|
||||||
|
color: !following ? 'brand' : 'white',
|
||||||
|
backgroundColor: !following ? 'none' : 'brand',
|
||||||
|
onClick: this.handleFollow,
|
||||||
|
}
|
||||||
|
buttonText = intl.formatMessage(following ? messages.unfollow : messages.follow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={[_s.default, _s.z1, _s.width100PC].join(' ')}>
|
<div className={[_s.default, _s.z1, _s.width100PC].join(' ')}>
|
||||||
|
|
||||||
@ -225,6 +256,30 @@ class ProfileHeader extends ImmutablePureComponent {
|
|||||||
<TabBar tabs={tabs} large />
|
<TabBar tabs={tabs} large />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{
|
||||||
|
account && account.get('id') === me &&
|
||||||
|
<div className={[_s.default, _s.flexRow, _s.marginLeftAuto, _s.py5].join(' ')}>
|
||||||
|
<Button
|
||||||
|
outline
|
||||||
|
backgroundColor='none'
|
||||||
|
color='brand'
|
||||||
|
className={[_s.justifyContentCenter, _s.alignItemsCenter].join(' ')}
|
||||||
|
href=''
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
color='inherit'
|
||||||
|
weight='bold'
|
||||||
|
size='medium'
|
||||||
|
className={[_s.px15].join(' ')}
|
||||||
|
>
|
||||||
|
Edit Profile
|
||||||
|
</Text>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
account && account.get('id') !== me &&
|
||||||
<div className={[_s.default, _s.flexRow, _s.marginLeftAuto, _s.py5].join(' ')}>
|
<div className={[_s.default, _s.flexRow, _s.marginLeftAuto, _s.py5].join(' ')}>
|
||||||
<div ref={this.setOpenMoreNodeRef}>
|
<div ref={this.setOpenMoreNodeRef}>
|
||||||
<Button
|
<Button
|
||||||
@ -240,7 +295,9 @@ class ProfileHeader extends ImmutablePureComponent {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<form action='https://chat.gab.com/private-message' method='POST'>
|
||||||
<Button
|
<Button
|
||||||
|
type='submit'
|
||||||
outline
|
outline
|
||||||
icon='chat'
|
icon='chat'
|
||||||
iconWidth='18px'
|
iconWidth='18px'
|
||||||
@ -249,26 +306,28 @@ class ProfileHeader extends ImmutablePureComponent {
|
|||||||
color='brand'
|
color='brand'
|
||||||
backgroundColor='none'
|
backgroundColor='none'
|
||||||
className={[_s.justifyContentCenter, _s.alignItemsCenter, _s.mr10, _s.px10].join(' ')}
|
className={[_s.justifyContentCenter, _s.alignItemsCenter, _s.mr10, _s.px10].join(' ')}
|
||||||
onClick={this.handleStartChat}
|
|
||||||
/>
|
/>
|
||||||
|
<input type='hidden' value={account.get('username')} name='username' />
|
||||||
|
</form>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
|
{...buttonOptions}
|
||||||
className={[_s.justifyContentCenter, _s.alignItemsCenter].join(' ')}
|
className={[_s.justifyContentCenter, _s.alignItemsCenter].join(' ')}
|
||||||
onClick={this.handleFollow}
|
|
||||||
>
|
>
|
||||||
<span className={[_s.px15].join(' ')}>
|
<span className={[_s.px15].join(' ')}>
|
||||||
<Text
|
<Text
|
||||||
color='white'
|
color='inherit'
|
||||||
weight='bold'
|
weight='bold'
|
||||||
size='medium'
|
size='medium'
|
||||||
className={[_s.px15].join(' ')}
|
className={[_s.px15].join(' ')}
|
||||||
>
|
>
|
||||||
Follow
|
{buttonText}
|
||||||
</Text>
|
</Text>
|
||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
43
app/javascript/gabsocial/components/setting_switch.js
Normal file
43
app/javascript/gabsocial/components/setting_switch.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
|
import Switch from './switch'
|
||||||
|
|
||||||
|
export default class SettingSwitch extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
prefix: PropTypes.string,
|
||||||
|
settings: ImmutablePropTypes.map.isRequired,
|
||||||
|
settingPath: PropTypes.array.isRequired,
|
||||||
|
description: PropTypes.string,
|
||||||
|
label: PropTypes.string.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange = ({ target }) => {
|
||||||
|
this.props.onChange(this.props.settingPath, target.checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const {
|
||||||
|
prefix,
|
||||||
|
settings,
|
||||||
|
settingPath,
|
||||||
|
label,
|
||||||
|
description
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
const id = ['setting-toggle', prefix, ...settingPath].filter(Boolean).join('-')
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Switch
|
||||||
|
description={description}
|
||||||
|
label={label}
|
||||||
|
id={id}
|
||||||
|
checked={settings.getIn(settingPath)}
|
||||||
|
onChange={this.onChange}
|
||||||
|
onKeyDown={this.onKeyDown}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1 +0,0 @@
|
|||||||
export { default } from './setting_toggle'
|
|
@ -1,32 +0,0 @@
|
|||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
|
||||||
import ToggleSwitch from '../toggle_switch';
|
|
||||||
|
|
||||||
|
|
||||||
export default class SettingToggle extends ImmutablePureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
prefix: PropTypes.string,
|
|
||||||
settings: ImmutablePropTypes.map.isRequired,
|
|
||||||
settingPath: PropTypes.array.isRequired,
|
|
||||||
label: PropTypes.node.isRequired,
|
|
||||||
onChange: PropTypes.func.isRequired,
|
|
||||||
}
|
|
||||||
|
|
||||||
onChange = ({ target }) => {
|
|
||||||
this.props.onChange(this.props.settingPath, target.checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { prefix, settings, settingPath, label } = this.props;
|
|
||||||
const id = ['setting-toggle', prefix, ...settingPath].filter(Boolean).join('-');
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className='setting-toggle'>
|
|
||||||
<ToggleSwitch id={id} checked={settings.getIn(settingPath)} onChange={this.onChange} onKeyDown={this.onKeyDown} />
|
|
||||||
<label htmlFor={id} className='setting-toggle__label'>{label}</label>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
.setting-toggle {
|
|
||||||
display: block;
|
|
||||||
line-height: 24px;
|
|
||||||
|
|
||||||
&__label {
|
|
||||||
color: $darker-text-color;
|
|
||||||
display: inline-block;
|
|
||||||
margin-bottom: 14px;
|
|
||||||
margin-left: 8px;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
@ -514,7 +514,7 @@ class Status extends ImmutablePureComponent {
|
|||||||
<StatusActionBar status={status} account={account} {...other} />
|
<StatusActionBar status={status} account={account} {...other} />
|
||||||
|
|
||||||
<div className={[_s.default, _s.borderTop1PX, _s.borderColorSecondary, _s.pt10, _s.px15, _s.mb10].join(' ')}>
|
<div className={[_s.default, _s.borderTop1PX, _s.borderColorSecondary, _s.pt10, _s.px15, _s.mb10].join(' ')}>
|
||||||
{/*<ComposeFormContainer replyToId={status.get('id')} shouldCondense />*/}
|
<ComposeFormContainer replyToId={status.get('id')} shouldCondense />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -2,11 +2,11 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
|||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { Set as ImmutableSet } from 'immutable';
|
import { Set as ImmutableSet } from 'immutable';
|
||||||
import noop from 'lodash/noop';
|
import noop from 'lodash/noop';
|
||||||
import { toggleStatusReport } from '../../actions/reports';
|
import { toggleStatusReport } from '../actions/reports';
|
||||||
import { MediaGallery, Video } from '../../features/ui/util/async-components';
|
import { MediaGallery, Video } from '../features/ui/util/async-components';
|
||||||
import Bundle from '../../features/ui/util/bundle';
|
import Bundle from '../features/ui/util/bundle';
|
||||||
import StatusContent from '../status_content';
|
import StatusContent from './status_content';
|
||||||
import ToggleSwitch from '../toggle_switch';
|
import Switch from './switch';
|
||||||
|
|
||||||
const mapStateToProps = (state, { id }) => ({
|
const mapStateToProps = (state, { id }) => ({
|
||||||
status: state.getIn(['statuses', id]),
|
status: state.getIn(['statuses', id]),
|
||||||
@ -34,9 +34,7 @@ class StatusCheckBox extends ImmutablePureComponent {
|
|||||||
const { status, checked, onToggle, disabled } = this.props;
|
const { status, checked, onToggle, disabled } = this.props;
|
||||||
let media = null;
|
let media = null;
|
||||||
|
|
||||||
if (status.get('reblog')) {
|
if (status.get('reblog')) return null
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status.get('media_attachments').size > 0) {
|
if (status.get('media_attachments').size > 0) {
|
||||||
if (status.get('media_attachments').some(item => item.get('type') === 'unknown')) {
|
if (status.get('media_attachments').some(item => item.get('type') === 'unknown')) {
|
||||||
@ -72,17 +70,17 @@ class StatusCheckBox extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='status-check-box'>
|
<div className={[_s.default, _s.flexRow].join(' ')}>
|
||||||
<div className='status-check-box__status'>
|
<div className={[_s.default].join(' ')}>
|
||||||
<StatusContent status={status} />
|
<StatusContent status={status} />
|
||||||
{media}
|
{media}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='status-check-box-toggle'>
|
<div className={[_s.default, _s.marginLeftAuto].join(' ')}>
|
||||||
<ToggleSwitch checked={checked} onChange={onToggle} disabled={disabled} />
|
<Switch checked={checked} onChange={onToggle} disabled={disabled} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1 +0,0 @@
|
|||||||
export { default } from './status_check_box'
|
|
@ -1,34 +0,0 @@
|
|||||||
.status-check-box {
|
|
||||||
display: flex;
|
|
||||||
border-bottom: 1px solid $ui-secondary-color;
|
|
||||||
|
|
||||||
&__status {
|
|
||||||
margin: 10px 0 10px 10px;
|
|
||||||
flex: 1;
|
|
||||||
|
|
||||||
.media-gallery {
|
|
||||||
max-width: 250px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status__content {
|
|
||||||
padding: 0;
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-player {
|
|
||||||
margin-top: 8px;
|
|
||||||
max-width: 250px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.media-gallery__item-thumbnail {
|
|
||||||
cursor: default;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__toggle {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
padding: 10px;
|
|
||||||
|
|
||||||
@include flex(center, center);
|
|
||||||
}
|
|
||||||
}
|
|
@ -130,15 +130,15 @@ class StatusContent extends ImmutablePureComponent {
|
|||||||
|
|
||||||
if (this.props.onExpandedToggle) {
|
if (this.props.onExpandedToggle) {
|
||||||
// The parent manages the state
|
// The parent manages the state
|
||||||
this.props.onExpandedToggle();
|
this.props.onExpandedToggle()
|
||||||
} else {
|
} else {
|
||||||
this.setState({ hidden: !this.state.hidden });
|
this.setState({ hidden: !this.state.hidden })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCollapsedClick = (e) => {
|
handleReadMore = (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.setState({ collapsed: !this.state.collapsed });
|
this.setState({ collapsed: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
setRef = (c) => {
|
setRef = (c) => {
|
||||||
@ -156,7 +156,8 @@ class StatusContent extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { status, intl, isComment } = this.props;
|
const { status, intl, isComment } = this.props
|
||||||
|
const { collapsed } = this.state
|
||||||
|
|
||||||
if (status.get('content').length === 0) return null;
|
if (status.get('content').length === 0) return null;
|
||||||
|
|
||||||
@ -213,12 +214,18 @@ class StatusContent extends ImmutablePureComponent {
|
|||||||
mb15: hasMarginBottom,
|
mb15: hasMarginBottom,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const statusContentClasses = cx({
|
||||||
|
statusContent: 1,
|
||||||
|
height220PX: collapsed,
|
||||||
|
overflowHidden: collapsed,
|
||||||
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={containerClasses}>
|
<div className={containerClasses}>
|
||||||
<div
|
<div
|
||||||
ref={this.setRef}
|
ref={this.setRef}
|
||||||
tabIndex='0'
|
tabIndex='0'
|
||||||
className={[_s.statusContent].join(' ')}
|
className={statusContentClasses}
|
||||||
style={directionStyle}
|
style={directionStyle}
|
||||||
dangerouslySetInnerHTML={content}
|
dangerouslySetInnerHTML={content}
|
||||||
lang={status.get('language')}
|
lang={status.get('language')}
|
||||||
@ -229,7 +236,7 @@ class StatusContent extends ImmutablePureComponent {
|
|||||||
this.state.collapsed &&
|
this.state.collapsed &&
|
||||||
<button
|
<button
|
||||||
className={[_s.default, _s.displayFlex, _s.cursorPointer, _s.py2, _s.text, _s.colorPrimary, _s.fontWeightBold, _s.fontSize15PX].join(' ')}
|
className={[_s.default, _s.displayFlex, _s.cursorPointer, _s.py2, _s.text, _s.colorPrimary, _s.fontWeightBold, _s.fontSize15PX].join(' ')}
|
||||||
onClick={this.props.onClick}
|
onClick={this.handleReadMore}
|
||||||
>
|
>
|
||||||
{intl.formatMessage(messages.readMore)}
|
{intl.formatMessage(messages.readMore)}
|
||||||
</button>
|
</button>
|
||||||
|
68
app/javascript/gabsocial/components/switch.js
Normal file
68
app/javascript/gabsocial/components/switch.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import classNames from 'classnames/bind'
|
||||||
|
import Text from './text'
|
||||||
|
|
||||||
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
|
export default class Switch extends PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
id: PropTypes.string.isRequired,
|
||||||
|
description: PropTypes.string,
|
||||||
|
label: PropTypes.string,
|
||||||
|
checked: PropTypes.bool,
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
onKeyDown: PropTypes.func,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
labelProps: PropTypes.object,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const {
|
||||||
|
id,
|
||||||
|
description,
|
||||||
|
label,
|
||||||
|
checked,
|
||||||
|
onChange,
|
||||||
|
onKeyDown,
|
||||||
|
disabled,
|
||||||
|
labelProps
|
||||||
|
} = this.props
|
||||||
|
|
||||||
|
const checkboxContainerClasses = cx({
|
||||||
|
cursorPointer: 1,
|
||||||
|
default: 1,
|
||||||
|
height24PX: 1,
|
||||||
|
width50PX: 1,
|
||||||
|
circle: 1,
|
||||||
|
border1PX: 1,
|
||||||
|
marginLeftAuto: 1,
|
||||||
|
borderColorSecondary: 1,
|
||||||
|
backgroundColorBrand: checked,
|
||||||
|
})
|
||||||
|
|
||||||
|
const checkboxLabelClasses = cx({
|
||||||
|
default: 1,
|
||||||
|
margin1PX: 1,
|
||||||
|
height20PX: 1,
|
||||||
|
width20PX: 1,
|
||||||
|
circle: 1,
|
||||||
|
positionAbsolute: 1,
|
||||||
|
backgroundSubtle2: !checked,
|
||||||
|
backgroundColorPrimary: checked,
|
||||||
|
left0: !checked,
|
||||||
|
right0: checked,
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[_s.default, _s.flexRow, _s.py5, _s.alignItemsCenter].join(' ')}>
|
||||||
|
<Text {...labelProps}>
|
||||||
|
{label}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<label className={checkboxContainerClasses} htmlFor={id}>
|
||||||
|
<span className={checkboxLabelClasses} />
|
||||||
|
<input type='checkbox' id={id} onChange={onChange} disabled={disabled} className={[_s.visibilityHidden].join(' ')} />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -1 +0,0 @@
|
|||||||
export { default } from './toggle_switch'
|
|
@ -1,7 +0,0 @@
|
|||||||
import Toggle from 'react-toggle'
|
|
||||||
|
|
||||||
export default class ToggleSwitch extends PureComponent {
|
|
||||||
render() {
|
|
||||||
return <Toggle {...this.props} />
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,95 +0,0 @@
|
|||||||
.react-toggle {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: transparent;
|
|
||||||
border: 0;
|
|
||||||
padding: 0;
|
|
||||||
-webkit-tap-highlight-color: rgba($base-overlay-background, 0);
|
|
||||||
-webkit-tap-highlight-color: transparent;
|
|
||||||
|
|
||||||
@include unselectable;
|
|
||||||
|
|
||||||
&--disabled {
|
|
||||||
cursor: not-allowed;
|
|
||||||
opacity: 0.5;
|
|
||||||
transition: opacity 0.25s;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-toggle-screenreader-only {
|
|
||||||
border: 0;
|
|
||||||
clip: rect(0 0 0 0);
|
|
||||||
margin: -1px;
|
|
||||||
overflow: hidden;
|
|
||||||
padding: 0;
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
@include size(1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-toggle-track {
|
|
||||||
padding: 0;
|
|
||||||
border-radius: 30px;
|
|
||||||
background-color: $ui-base-color;
|
|
||||||
transition: background-color 0.2s ease;
|
|
||||||
|
|
||||||
@include size(50px, 24px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-toggle:hover:not(.react-toggle--disabled) .react-toggle-track {
|
|
||||||
background-color: darken($ui-base-color, 10%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-toggle--checked .react-toggle-track {
|
|
||||||
background-color: $gab-brand-default;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-toggle--checked:hover:not(.react-toggle--disabled) .react-toggle-track {
|
|
||||||
background-color: lighten($gab-brand-default, 10%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-toggle-track-check {
|
|
||||||
line-height: 0;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.25s ease;
|
|
||||||
|
|
||||||
@include abs-position(0, auto, 0, 8px);
|
|
||||||
@include size(14px, 10px);
|
|
||||||
@include vertical-margin(auto);
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-toggle--checked .react-toggle-track-check {
|
|
||||||
opacity: 1;
|
|
||||||
transition: opacity 0.25s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-toggle-track-x {
|
|
||||||
line-height: 0;
|
|
||||||
opacity: 1;
|
|
||||||
transition: opacity 0.25s ease;
|
|
||||||
|
|
||||||
@include abs-position(0, 10px, 0);
|
|
||||||
@include size(10px);
|
|
||||||
@include vertical-margin(auto);
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-toggle--checked .react-toggle-track-x {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-toggle-thumb {
|
|
||||||
border: 1px solid $ui-base-color;
|
|
||||||
background-color: darken($simple-background-color, 2%);
|
|
||||||
box-sizing: border-box;
|
|
||||||
transition: all 0.25s ease;
|
|
||||||
transition-property: border-color, left;
|
|
||||||
|
|
||||||
@include abs-position(1, auto, auto, 1px);
|
|
||||||
@include circle(22px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.react-toggle--checked .react-toggle-thumb {
|
|
||||||
left: 27px;
|
|
||||||
border-color: $gab-brand-default;
|
|
||||||
}
|
|
@ -44,6 +44,10 @@ export default class TrendingItem extends ImmutablePureComponent {
|
|||||||
underline: hovering,
|
underline: hovering,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// : todo :
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavLink
|
<NavLink
|
||||||
to='/test'
|
to='/test'
|
||||||
|
@ -32,10 +32,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||||||
onFollow (account) {
|
onFollow (account) {
|
||||||
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
|
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
|
||||||
if (unfollowModal) {
|
if (unfollowModal) {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('UNFOLLOW', {
|
||||||
message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
accountId: account.get('id'),
|
||||||
confirm: intl.formatMessage(messages.unfollowConfirm),
|
|
||||||
onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
|
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
dispatch(unfollowAccount(account.get('id')))
|
dispatch(unfollowAccount(account.get('id')))
|
||||||
|
@ -1,24 +1,22 @@
|
|||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||||
import { blockDomain, unblockDomain } from '../actions/domain_blocks';
|
import { blockDomain, unblockDomain } from '../actions/domain_blocks'
|
||||||
import { openModal } from '../actions/modal';
|
import { openModal } from '../actions/modal'
|
||||||
import Domain from '../components/domain';
|
import Domain from '../components/domain'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' },
|
blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' },
|
||||||
});
|
})
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch, { intl }) => ({
|
const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
onBlockDomain (domain) {
|
onBlockDomain (domain) {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('BLOCK_DOMAIN', {
|
||||||
message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.' values={{ domain: <strong>{domain}</strong> }} />,
|
domain,
|
||||||
confirm: intl.formatMessage(messages.blockDomainConfirm),
|
}))
|
||||||
onConfirm: () => dispatch(blockDomain(domain)),
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onUnblockDomain (domain) {
|
onUnblockDomain (domain) {
|
||||||
dispatch(unblockDomain(domain));
|
dispatch(unblockDomain(domain))
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
export default injectIntl(connect(null, mapDispatchToProps)(Domain));
|
export default injectIntl(connect(null, mapDispatchToProps)(Domain))
|
||||||
|
@ -36,7 +36,6 @@ import Status from '../components/status';
|
|||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
||||||
deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
|
deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
|
||||||
blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
|
|
||||||
replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' },
|
replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' },
|
||||||
replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' },
|
replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' },
|
||||||
quoteConfirm: { id: 'confirmations.quote.confirm', defaultMessage: 'Quote' },
|
quoteConfirm: { id: 'confirmations.quote.confirm', defaultMessage: 'Quote' },
|
||||||
@ -162,17 +161,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onBlock (status) {
|
onBlock (status) {
|
||||||
const account = status.get('account');
|
const account = status.get('account')
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('BLOCK_ACCOUNT', {
|
||||||
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
accountId: account.get('id'),
|
||||||
confirm: intl.formatMessage(messages.blockConfirm),
|
}))
|
||||||
onConfirm: () => dispatch(blockAccount(account.get('id'))),
|
|
||||||
secondary: intl.formatMessage(messages.blockAndReport),
|
|
||||||
onSecondary: () => {
|
|
||||||
dispatch(blockAccount(account.get('id')));
|
|
||||||
dispatch(initReport(account, status));
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onReport (status) {
|
onReport (status) {
|
||||||
|
@ -22,7 +22,6 @@ import Header from '../components/header';
|
|||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' },
|
unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' },
|
||||||
blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
|
|
||||||
blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' },
|
blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' },
|
||||||
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
|
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
|
||||||
});
|
});
|
||||||
@ -44,16 +43,14 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||||||
onFollow (account) {
|
onFollow (account) {
|
||||||
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
|
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
|
||||||
if (unfollowModal) {
|
if (unfollowModal) {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('UNFOLLOW', {
|
||||||
message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
accountId: account.get('id'),
|
||||||
confirm: intl.formatMessage(messages.unfollowConfirm),
|
}))
|
||||||
onConfirm: () => dispatch(unfollowAccount(account.get('id'))),
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
dispatch(unfollowAccount(account.get('id')));
|
dispatch(unfollowAccount(account.get('id')))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dispatch(followAccount(account.get('id')));
|
dispatch(followAccount(account.get('id')))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -61,15 +58,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||||||
if (account.getIn(['relationship', 'blocking'])) {
|
if (account.getIn(['relationship', 'blocking'])) {
|
||||||
dispatch(unblockAccount(account.get('id')));
|
dispatch(unblockAccount(account.get('id')));
|
||||||
} else {
|
} else {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('BLOCK_ACCOUNT', {
|
||||||
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
accountId: account.get('id'),
|
||||||
confirm: intl.formatMessage(messages.blockConfirm),
|
|
||||||
onConfirm: () => dispatch(blockAccount(account.get('id'))),
|
|
||||||
secondary: intl.formatMessage(messages.blockAndReport),
|
|
||||||
onSecondary: () => {
|
|
||||||
dispatch(blockAccount(account.get('id')));
|
|
||||||
dispatch(initReport(account));
|
|
||||||
},
|
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -107,10 +97,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onBlockDomain (domain) {
|
onBlockDomain (domain) {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('BLOCK_DOMAIN', {
|
||||||
message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications. Your followers from that domain will be removed.' values={{ domain: <strong>{domain}</strong> }} />,
|
domain,
|
||||||
confirm: intl.formatMessage(messages.blockDomainConfirm),
|
|
||||||
onConfirm: () => dispatch(blockDomain(domain)),
|
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1,20 +1,20 @@
|
|||||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
import { defineMessages, injectIntl } from 'react-intl'
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||||
import { debounce } from 'lodash'
|
import { debounce } from 'lodash'
|
||||||
import ColumnIndicator from '../components/column_indicator'
|
|
||||||
import AccountContainer from '../containers/account_container'
|
|
||||||
import { fetchBlocks, expandBlocks } from '../actions/blocks'
|
import { fetchBlocks, expandBlocks } from '../actions/blocks'
|
||||||
|
import AccountContainer from '../containers/account_container'
|
||||||
|
import ColumnIndicator from '../components/column_indicator'
|
||||||
import ScrollableList from '../components/scrollable_list'
|
import ScrollableList from '../components/scrollable_list'
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
heading: { id: 'column.blocks', defaultMessage: 'Blocked users' },
|
empty: { id: 'empty_column.blocks', defaultMessage: 'You haven\'t blocked any users yet.' },
|
||||||
});
|
})
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
accountIds: state.getIn(['user_lists', 'blocks', 'items']),
|
accountIds: state.getIn(['user_lists', 'blocks', 'items']),
|
||||||
hasMore: !!state.getIn(['user_lists', 'blocks', 'next']),
|
hasMore: !!state.getIn(['user_lists', 'blocks', 'next']),
|
||||||
});
|
})
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@connect(mapStateToProps)
|
@connect(mapStateToProps)
|
||||||
@ -27,35 +27,43 @@ class Blocks extends ImmutablePureComponent {
|
|||||||
accountIds: ImmutablePropTypes.list,
|
accountIds: ImmutablePropTypes.list,
|
||||||
hasMore: PropTypes.bool,
|
hasMore: PropTypes.bool,
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
};
|
}
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount() {
|
||||||
this.props.dispatch(fetchBlocks());
|
this.props.dispatch(fetchBlocks())
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLoadMore = debounce(() => {
|
handleLoadMore = debounce(() => {
|
||||||
this.props.dispatch(expandBlocks());
|
this.props.dispatch(expandBlocks())
|
||||||
}, 300, { leading: true });
|
}, 300, { leading: true })
|
||||||
|
|
||||||
render () {
|
render() {
|
||||||
const { intl, accountIds, hasMore } = this.props;
|
const {
|
||||||
|
intl,
|
||||||
|
accountIds,
|
||||||
|
hasMore
|
||||||
|
} = this.props
|
||||||
|
|
||||||
if (!accountIds) {
|
if (!accountIds) {
|
||||||
return (<ColumnIndicator type='loading' />);
|
return <ColumnIndicator type='loading' />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const emptyMessage = intl.formatMessage(messages.empty)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='blocks'
|
scrollKey='blocks'
|
||||||
onLoadMore={this.handleLoadMore}
|
onLoadMore={this.handleLoadMore}
|
||||||
hasMore={hasMore}
|
hasMore={hasMore}
|
||||||
emptyMessage={<FormattedMessage id='empty_column.blocks' defaultMessage="You haven't blocked any users yet." />}
|
emptyMessage={emptyMessage}
|
||||||
>
|
>
|
||||||
{accountIds.map(id =>
|
{
|
||||||
<AccountContainer key={id} id={id} />
|
accountIds.map(id =>
|
||||||
)}
|
<AccountContainer key={`blocked-${id}`} id={id} compact />
|
||||||
|
)
|
||||||
|
}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
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 } from 'react-intl';
|
||||||
import SettingToggle from '../../../../components/setting_toggle';
|
import SettingSwitch from '../../../../components/setting_switch';
|
||||||
import { changeSetting } from '../../../../actions/settings';
|
import { changeSetting } from '../../../../actions/settings';
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
@ -30,13 +30,13 @@ class ColumnSettings extends ImmutablePureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SettingToggle
|
<SettingSwitch
|
||||||
settings={settings}
|
settings={settings}
|
||||||
settingPath={['other', 'onlyMedia']}
|
settingPath={['other', 'onlyMedia']}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
label={<FormattedMessage id='community.column_settings.media_only' defaultMessage='Media Only' />}
|
label={<FormattedMessage id='community.column_settings.media_only' defaultMessage='Media Only' />}
|
||||||
/>
|
/>
|
||||||
<SettingToggle
|
<SettingSwitch
|
||||||
settings={settings}
|
settings={settings}
|
||||||
settingPath={['other', 'allFediverse']}
|
settingPath={['other', 'allFediverse']}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
|
@ -49,7 +49,7 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
edit: PropTypes.bool.isRequired,
|
edit: PropTypes.bool,
|
||||||
text: PropTypes.string.isRequired,
|
text: PropTypes.string.isRequired,
|
||||||
suggestions: ImmutablePropTypes.list,
|
suggestions: ImmutablePropTypes.list,
|
||||||
account: ImmutablePropTypes.map.isRequired,
|
account: ImmutablePropTypes.map.isRequired,
|
||||||
|
@ -29,7 +29,6 @@ class EmojiPickerButton extends PureComponent {
|
|||||||
unavailable: PropTypes.bool,
|
unavailable: PropTypes.bool,
|
||||||
active: PropTypes.bool,
|
active: PropTypes.bool,
|
||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
intl: PropTypes.object.isRequired,
|
|
||||||
small: PropTypes.bool,
|
small: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ class SpoilerButton extends PureComponent {
|
|||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
active: PropTypes.bool,
|
active: PropTypes.bool,
|
||||||
intl: PropTypes.map,
|
intl: PropTypes.object.isRequired,
|
||||||
small: PropTypes.bool,
|
small: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ class Favorites extends ImmutablePureComponent {
|
|||||||
>
|
>
|
||||||
{
|
{
|
||||||
accountIds.map(id =>
|
accountIds.map(id =>
|
||||||
<AccountContainer key={id} id={id} withNote={false} />
|
<AccountContainer key={id} id={id} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
|
@ -88,7 +88,7 @@ class Followers extends ImmutablePureComponent {
|
|||||||
>
|
>
|
||||||
{
|
{
|
||||||
!!accountIds && accountIds.map((id) => (
|
!!accountIds && accountIds.map((id) => (
|
||||||
<AccountContainer key={`follower-${id}`} id={id} withNote={false} compact />
|
<AccountContainer key={`follower-${id}`} id={id} compact />
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
|
@ -88,7 +88,7 @@ class Following extends ImmutablePureComponent {
|
|||||||
>
|
>
|
||||||
{
|
{
|
||||||
!!accountIds && accountIds.map((id) => (
|
!!accountIds && accountIds.map((id) => (
|
||||||
<AccountContainer key={`following-${id}`} id={id} withNote={false} compact />
|
<AccountContainer key={`following-${id}`} id={id} compact />
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
|
@ -71,7 +71,7 @@ class GroupMembers extends ImmutablePureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="group-account-wrapper" key={id}>
|
<div className="group-account-wrapper" key={id}>
|
||||||
<AccountContainer id={id} withNote={false} actionIcon="none" onActionClick={() => true} />
|
<AccountContainer id={id} actionIcon="none" onActionClick={() => true} />
|
||||||
{ /*
|
{ /*
|
||||||
menu.length > 0 && <DropdownMenuContainer items={menu} icon='ellipsis-h' size={18} direction='right' />
|
menu.length > 0 && <DropdownMenuContainer items={menu} icon='ellipsis-h' size={18} direction='right' />
|
||||||
*/
|
*/
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { injectIntl, FormattedMessage } from 'react-intl';
|
import { injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import SettingToggle from '../../../../components/setting_toggle';
|
import SettingSwitch from '../../../../components/setting_switch';
|
||||||
|
|
||||||
export default
|
export default
|
||||||
@injectIntl
|
@injectIntl
|
||||||
@ -20,7 +20,7 @@ class ColumnSettings extends PureComponent {
|
|||||||
<span className='column-settings__section'><FormattedMessage id='home.column_settings.basic' defaultMessage='Basic' /></span>
|
<span className='column-settings__section'><FormattedMessage id='home.column_settings.basic' defaultMessage='Basic' /></span>
|
||||||
|
|
||||||
<div className='column-settings__row'>
|
<div className='column-settings__row'>
|
||||||
<SettingToggle prefix='home_timeline' settings={settings} settingPath={['shows', 'reply']} onChange={onChange} label={<FormattedMessage id='home.column_settings.show_replies' defaultMessage='Show replies' />} />
|
<SettingSwitch prefix='home_timeline' settings={settings} settingPath={['shows', 'reply']} onChange={onChange} label={<FormattedMessage id='home.column_settings.show_replies' defaultMessage='Show replies' />} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -42,7 +42,7 @@ getActionButton() {
|
|||||||
|
|
||||||
const menu = [
|
const menu = [
|
||||||
{ text: intl.formatMessage(messages.edit), to: `/groups/${group.get('id')}/edit` },
|
{ text: intl.formatMessage(messages.edit), to: `/groups/${group.get('id')}/edit` },
|
||||||
{ text: intl.formatMessage(messages.removed_accounts), to: `/groups/${group.get('id')}/removed_accounts` },
|
{ text: intl.formatMessage(messages.removed_accounts), to: `/groups/${group.get('id')}/removed-accounts` },
|
||||||
];
|
];
|
||||||
|
|
||||||
// <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' />;
|
// <DropdownMenuContainer items={menu} icon='ellipsis-v' size={24} direction='right' />;
|
||||||
|
@ -2,7 +2,7 @@ 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 } from 'react-intl';
|
||||||
import { changeSetting, saveSettings } from '../../../../actions/settings';
|
import { changeSetting, saveSettings } from '../../../../actions/settings';
|
||||||
import SettingToggle from '../../../../components/setting_toggle';
|
import SettingSwitch from '../../../../components/setting_switch';
|
||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
settings: state.getIn(['settings', 'home']),
|
settings: state.getIn(['settings', 'home']),
|
||||||
@ -33,7 +33,7 @@ class ColumnSettings extends ImmutablePureComponent {
|
|||||||
<div>
|
<div>
|
||||||
<FormattedMessage id='home.column_settings.basic' defaultMessage='Basic' />
|
<FormattedMessage id='home.column_settings.basic' defaultMessage='Basic' />
|
||||||
|
|
||||||
<SettingToggle
|
<SettingSwitch
|
||||||
prefix='home_timeline'
|
prefix='home_timeline'
|
||||||
settings={settings}
|
settings={settings}
|
||||||
settingPath={['shows', 'repost']}
|
settingPath={['shows', 'repost']}
|
||||||
@ -41,7 +41,7 @@ class ColumnSettings extends ImmutablePureComponent {
|
|||||||
label={<FormattedMessage id='home.column_settings.show_reposts' defaultMessage='Show reposts' />}
|
label={<FormattedMessage id='home.column_settings.show_reposts' defaultMessage='Show reposts' />}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<SettingToggle
|
<SettingSwitch
|
||||||
prefix='home_timeline'
|
prefix='home_timeline'
|
||||||
settings={settings}
|
settings={settings}
|
||||||
settingPath={['shows', 'reply']}
|
settingPath={['shows', 'reply']}
|
||||||
|
@ -18,7 +18,7 @@ const mapStateToProps = (state, { params: { username } }) => {
|
|||||||
|
|
||||||
export default
|
export default
|
||||||
@connect(mapStateToProps)
|
@connect(mapStateToProps)
|
||||||
class Favorites extends ImmutablePureComponent {
|
class LikedStatuses extends ImmutablePureComponent {
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
dispatch: PropTypes.func.isRequired,
|
dispatch: PropTypes.func.isRequired,
|
||||||
@ -43,16 +43,14 @@ class Favorites extends ImmutablePureComponent {
|
|||||||
return <ColumnIndicator type='missing' />
|
return <ColumnIndicator type='missing' />
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("statusIds:", statusIds)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StatusList
|
<StatusList
|
||||||
statusIds={statusIds}
|
statusIds={statusIds}
|
||||||
scrollKey='favorited_statuses'
|
scrollKey='liked_statuses'
|
||||||
hasMore={hasMore}
|
hasMore={hasMore}
|
||||||
isLoading={isLoading}
|
isLoading={isLoading}
|
||||||
onLoadMore={this.handleLoadMore}
|
onLoadMore={this.handleLoadMore}
|
||||||
emptyMessage={<FormattedMessage id='empty_column.favorited_statuses' defaultMessage="You don't have any favorite gabs yet. When you favorite one, it will show up here." />}
|
emptyMessage={<FormattedMessage id='empty_column.liked_statuses' defaultMessage="You don't have any liked gabs yet. When you like one, it will show up here." />}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ 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 } from 'react-intl';
|
||||||
import ColumnHeaderSettingButton from '../../../../components/column_header_setting_button';
|
import ColumnHeaderSettingButton from '../../../../components/column_header_setting_button';
|
||||||
import SettingToggle from '../../../../components/setting_toggle';
|
import SettingSwitch from '../../../../components/setting_switch';
|
||||||
|
|
||||||
export default class ColumnSettings extends ImmutablePureComponent {
|
export default class ColumnSettings extends ImmutablePureComponent {
|
||||||
|
|
||||||
@ -39,48 +39,48 @@ export default class ColumnSettings extends ImmutablePureComponent {
|
|||||||
|
|
||||||
<div role='group' aria-labelledby='notifications-filter-bar'>
|
<div role='group' aria-labelledby='notifications-filter-bar'>
|
||||||
<FormattedMessage id='notifications.column_settings.filter_bar.category' defaultMessage='Quick filter bar' />
|
<FormattedMessage id='notifications.column_settings.filter_bar.category' defaultMessage='Quick filter bar' />
|
||||||
<SettingToggle id='show-filter-bar' prefix='notifications' settings={settings} settingPath={['quickFilter', 'show']} onChange={onChange} label={filterShowStr} />
|
<SettingSwitch id='show-filter-bar' prefix='notifications' settings={settings} settingPath={['quickFilter', 'show']} onChange={onChange} label={filterShowStr} />
|
||||||
<SettingToggle id='show-filter-bar' prefix='notifications' settings={settings} settingPath={['quickFilter', 'advanced']} onChange={onChange} label={filterAdvancedStr} />
|
<SettingSwitch id='show-filter-bar' prefix='notifications' settings={settings} settingPath={['quickFilter', 'advanced']} onChange={onChange} label={filterAdvancedStr} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div role='group' aria-labelledby='notifications-follow'>
|
<div role='group' aria-labelledby='notifications-follow'>
|
||||||
<FormattedMessage id='notifications.column_settings.follow' defaultMessage='New followers:' />
|
<FormattedMessage id='notifications.column_settings.follow' defaultMessage='New followers:' />
|
||||||
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'follow']} onChange={onChange} label={alertStr} />
|
<SettingSwitch prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'follow']} onChange={onChange} label={alertStr} />
|
||||||
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'follow']} onChange={this.onPushChange} label={pushStr} />}
|
{showPushSettings && <SettingSwitch prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'follow']} onChange={this.onPushChange} label={pushStr} />}
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'follow']} onChange={onChange} label={showStr} />
|
<SettingSwitch prefix='notifications' settings={settings} settingPath={['shows', 'follow']} onChange={onChange} label={showStr} />
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'follow']} onChange={onChange} label={soundStr} />
|
<SettingSwitch prefix='notifications' settings={settings} settingPath={['sounds', 'follow']} onChange={onChange} label={soundStr} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div role='group' aria-labelledby='notifications-favorite'>
|
<div role='group' aria-labelledby='notifications-favorite'>
|
||||||
<FormattedMessage id='notifications.column_settings.favorite' defaultMessage='Favorites:' />
|
<FormattedMessage id='notifications.column_settings.favorite' defaultMessage='Favorites:' />
|
||||||
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'favorite']} onChange={onChange} label={alertStr} />
|
<SettingSwitch prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'favorite']} onChange={onChange} label={alertStr} />
|
||||||
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'favorite']} onChange={this.onPushChange} label={pushStr} />}
|
{showPushSettings && <SettingSwitch prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'favorite']} onChange={this.onPushChange} label={pushStr} />}
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'favorite']} onChange={onChange} label={showStr} />
|
<SettingSwitch prefix='notifications' settings={settings} settingPath={['shows', 'favorite']} onChange={onChange} label={showStr} />
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'favorite']} onChange={onChange} label={soundStr} />
|
<SettingSwitch prefix='notifications' settings={settings} settingPath={['sounds', 'favorite']} onChange={onChange} label={soundStr} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div role='group' aria-labelledby='notifications-mention'>
|
<div role='group' aria-labelledby='notifications-mention'>
|
||||||
<FormattedMessage id='notifications.column_settings.mention' defaultMessage='Mentions:' />
|
<FormattedMessage id='notifications.column_settings.mention' defaultMessage='Mentions:' />
|
||||||
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'mention']} onChange={onChange} label={alertStr} />
|
<SettingSwitch prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'mention']} onChange={onChange} label={alertStr} />
|
||||||
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'mention']} onChange={this.onPushChange} label={pushStr} />}
|
{showPushSettings && <SettingSwitch prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'mention']} onChange={this.onPushChange} label={pushStr} />}
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'mention']} onChange={onChange} label={showStr} />
|
<SettingSwitch prefix='notifications' settings={settings} settingPath={['shows', 'mention']} onChange={onChange} label={showStr} />
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'mention']} onChange={onChange} label={soundStr} />
|
<SettingSwitch prefix='notifications' settings={settings} settingPath={['sounds', 'mention']} onChange={onChange} label={soundStr} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div role='group' aria-labelledby='notifications-repost'>
|
<div role='group' aria-labelledby='notifications-repost'>
|
||||||
<FormattedMessage id='notifications.column_settings.repost' defaultMessage='Reposts:' />
|
<FormattedMessage id='notifications.column_settings.repost' defaultMessage='Reposts:' />
|
||||||
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'repost']} onChange={onChange} label={alertStr} />
|
<SettingSwitch prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'repost']} onChange={onChange} label={alertStr} />
|
||||||
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'repost']} onChange={this.onPushChange} label={pushStr} />}
|
{showPushSettings && <SettingSwitch prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'repost']} onChange={this.onPushChange} label={pushStr} />}
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'repost']} onChange={onChange} label={showStr} />
|
<SettingSwitch prefix='notifications' settings={settings} settingPath={['shows', 'repost']} onChange={onChange} label={showStr} />
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'repost']} onChange={onChange} label={soundStr} />
|
<SettingSwitch prefix='notifications' settings={settings} settingPath={['sounds', 'repost']} onChange={onChange} label={soundStr} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div role='group' aria-labelledby='notifications-poll'>
|
<div role='group' aria-labelledby='notifications-poll'>
|
||||||
<FormattedMessage id='notifications.column_settings.poll' defaultMessage='Poll results:' />
|
<FormattedMessage id='notifications.column_settings.poll' defaultMessage='Poll results:' />
|
||||||
<SettingToggle prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'poll']} onChange={onChange} label={alertStr} />
|
<SettingSwitch prefix='notifications_desktop' settings={settings} settingPath={['alerts', 'poll']} onChange={onChange} label={alertStr} />
|
||||||
{showPushSettings && <SettingToggle prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'poll']} onChange={this.onPushChange} label={pushStr} />}
|
{showPushSettings && <SettingSwitch prefix='notifications_push' settings={pushSettings} settingPath={['alerts', 'poll']} onChange={this.onPushChange} label={pushStr} />}
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['shows', 'poll']} onChange={onChange} label={showStr} />
|
<SettingSwitch prefix='notifications' settings={settings} settingPath={['shows', 'poll']} onChange={onChange} label={showStr} />
|
||||||
<SettingToggle prefix='notifications' settings={settings} settingPath={['sounds', 'poll']} onChange={onChange} label={soundStr} />
|
<SettingSwitch prefix='notifications' settings={settings} settingPath={['sounds', 'poll']} onChange={onChange} label={soundStr} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -117,7 +117,7 @@ class Notification extends ImmutablePureComponent {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<AccountContainer id={account.get('id')} withNote={false} hidden={this.props.hidden} />
|
<AccountContainer id={account.get('id')} hidden={this.props.hidden} />
|
||||||
</div>
|
</div>
|
||||||
</HotKeys>
|
</HotKeys>
|
||||||
);
|
);
|
||||||
|
@ -60,7 +60,7 @@ class Reposts extends ImmutablePureComponent {
|
|||||||
>
|
>
|
||||||
{
|
{
|
||||||
accountIds.map(id =>
|
accountIds.map(id =>
|
||||||
<AccountContainer key={id} id={id} withNote={false} />
|
<AccountContainer key={id} id={id} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
</ScrollableList>
|
</ScrollableList>
|
||||||
|
@ -30,7 +30,6 @@ import DetailedStatus from '../components/detailed_status';
|
|||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
|
||||||
deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
|
deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
|
||||||
blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
|
|
||||||
replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' },
|
replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' },
|
||||||
replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' },
|
replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' },
|
||||||
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
|
blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
|
||||||
@ -128,17 +127,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onBlock (status) {
|
onBlock (status) {
|
||||||
const account = status.get('account');
|
const account = status.get('account')
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('BLOCK_ACCOUNT', {
|
||||||
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
accountId: account.get('id'),
|
||||||
confirm: intl.formatMessage(messages.blockConfirm),
|
}))
|
||||||
onConfirm: () => dispatch(blockAccount(account.get('id'))),
|
|
||||||
secondary: intl.formatMessage(messages.blockAndReport),
|
|
||||||
onSecondary: () => {
|
|
||||||
dispatch(blockAccount(account.get('id')));
|
|
||||||
dispatch(initReport(account, status));
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onReport (status) {
|
onReport (status) {
|
||||||
|
@ -40,7 +40,6 @@ const messages = defineMessages({
|
|||||||
deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
|
deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
|
||||||
redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
|
redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
|
||||||
redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? Favorites and reposts will be lost, and replies to the original post will be orphaned.' },
|
redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? Favorites and reposts will be lost, and replies to the original post will be orphaned.' },
|
||||||
blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
|
|
||||||
revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' },
|
revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' },
|
||||||
hideAll: { id: 'status.show_less_all', defaultMessage: 'Show less for all' },
|
hideAll: { id: 'status.show_less_all', defaultMessage: 'Show less for all' },
|
||||||
detailedStatus: { id: 'status.detailed_status', defaultMessage: 'Detailed conversation view' },
|
detailedStatus: { id: 'status.detailed_status', defaultMessage: 'Detailed conversation view' },
|
||||||
@ -237,19 +236,12 @@ class Status extends ImmutablePureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleBlockClick = (status) => {
|
handleBlockClick = (status) => {
|
||||||
const { dispatch, intl } = this.props;
|
const { dispatch } = this.props
|
||||||
const account = status.get('account');
|
const account = status.get('account')
|
||||||
|
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('BLOCK_ACCOUNT', {
|
||||||
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
accountId: account.get('id'),
|
||||||
confirm: intl.formatMessage(messages.blockConfirm),
|
}))
|
||||||
onConfirm: () => dispatch(blockAccount(account.get('id'))),
|
|
||||||
secondary: intl.formatMessage(messages.blockAndReport),
|
|
||||||
onSecondary: () => {
|
|
||||||
dispatch(blockAccount(account.get('id')));
|
|
||||||
dispatch(initReport(account, status));
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleReport = (status) => {
|
handleReport = (status) => {
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
initializeNotifications,
|
initializeNotifications,
|
||||||
expandNotifications,
|
expandNotifications,
|
||||||
} from '../../actions/notifications'
|
} from '../../actions/notifications'
|
||||||
|
import LoadingBarContainer from '../../containers/loading_bar_container'
|
||||||
import { fetchFilters } from '../../actions/filters'
|
import { fetchFilters } from '../../actions/filters'
|
||||||
import { clearHeight } from '../../actions/height_cache'
|
import { clearHeight } from '../../actions/height_cache'
|
||||||
import { openModal } from '../../actions/modal'
|
import { openModal } from '../../actions/modal'
|
||||||
@ -37,7 +38,7 @@ import {
|
|||||||
CommunityTimeline,
|
CommunityTimeline,
|
||||||
DomainBlocks,
|
DomainBlocks,
|
||||||
Favorites,
|
Favorites,
|
||||||
FavoritedStatuses,
|
Filters,
|
||||||
Followers,
|
Followers,
|
||||||
Following,
|
Following,
|
||||||
FollowRequests,
|
FollowRequests,
|
||||||
@ -50,6 +51,7 @@ import {
|
|||||||
GroupTimeline,
|
GroupTimeline,
|
||||||
HashtagTimeline,
|
HashtagTimeline,
|
||||||
HomeTimeline,
|
HomeTimeline,
|
||||||
|
LikedStatuses,
|
||||||
ListCreate,
|
ListCreate,
|
||||||
ListsDirectory,
|
ListsDirectory,
|
||||||
ListEdit,
|
ListEdit,
|
||||||
@ -148,7 +150,7 @@ class SwitchingArea extends PureComponent {
|
|||||||
|
|
||||||
<WrappedRoute path='/groups/create' page={ModalPage} component={GroupCreate} content={children} componentParams={{ title: 'Create Group' }} />
|
<WrappedRoute path='/groups/create' page={ModalPage} component={GroupCreate} content={children} componentParams={{ title: 'Create Group' }} />
|
||||||
<WrappedRoute path='/groups/:id/members' page={GroupPage} component={GroupMembers} content={children} />
|
<WrappedRoute path='/groups/:id/members' page={GroupPage} component={GroupMembers} content={children} />
|
||||||
<WrappedRoute path='/groups/:id/removed_accounts' page={GroupPage} component={GroupRemovedAccounts} content={children} />
|
<WrappedRoute path='/groups/:id/removed-accounts' page={GroupPage} component={GroupRemovedAccounts} content={children} />
|
||||||
<WrappedRoute path='/groups/:id/edit' page={ModalPage} component={GroupCreate} content={children} componentParams={{ title: 'Edit Group' }} />
|
<WrappedRoute path='/groups/:id/edit' page={ModalPage} component={GroupCreate} content={children} componentParams={{ title: 'Edit Group' }} />
|
||||||
<WrappedRoute path='/groups/:id' page={GroupPage} component={GroupTimeline} content={children} />
|
<WrappedRoute path='/groups/:id' page={GroupPage} component={GroupTimeline} content={children} />
|
||||||
|
|
||||||
@ -169,22 +171,21 @@ class SwitchingArea extends PureComponent {
|
|||||||
{ /*
|
{ /*
|
||||||
<WrappedRoute path='/settings/account' exact page={SettingsPage} component={AccountSettings} content={children} />
|
<WrappedRoute path='/settings/account' exact page={SettingsPage} component={AccountSettings} content={children} />
|
||||||
<WrappedRoute path='/settings/profile' exact page={SettingsPage} component={ProfileSettings} content={children} />
|
<WrappedRoute path='/settings/profile' exact page={SettingsPage} component={ProfileSettings} content={children} />
|
||||||
<WrappedRoute path='/settings/domain_blocks' exact page={SettingsPage} component={DomainBlocks} content={children} />
|
|
||||||
<WrappedRoute path='/settings/relationships' exact page={SettingsPage} component={RelationshipSettings} content={children} />
|
<WrappedRoute path='/settings/relationships' exact page={SettingsPage} component={RelationshipSettings} content={children} />
|
||||||
<WrappedRoute path='/settings/filters' exact page={SettingsPage} component={Filters} content={children} />
|
|
||||||
<WrappedRoute path='/settings/blocks' exact page={SettingsPage} component={Blocks} content={children} />
|
|
||||||
<WrappedRoute path='/settings/mutes' exact page={SettingsPage} component={Mutes} content={children} />
|
|
||||||
<WrappedRoute path='/settings/development' exact page={SettingsPage} component={Development} content={children} />
|
<WrappedRoute path='/settings/development' exact page={SettingsPage} component={Development} content={children} />
|
||||||
<WrappedRoute path='/settings/billing' exact page={SettingsPage} component={Billing} content={children} />
|
<WrappedRoute path='/settings/billing' exact page={SettingsPage} component={Billing} content={children} />
|
||||||
*/ }
|
*/ }
|
||||||
|
|
||||||
|
<WrappedRoute path='/settings/blocks' exact page={SettingsPage} component={Blocks} content={children} componentParams={{ title: 'Blocked Accounts' }} />
|
||||||
|
<WrappedRoute path='/settings/domain-blocks' exact page={SettingsPage} component={DomainBlocks} content={children} componentParams={{ title: 'Domain Blocks' }} />
|
||||||
|
<WrappedRoute path='/settings/filters' exact page={SettingsPage} component={Filters} content={children} componentParams={{ title: 'Muted Words' }} />
|
||||||
|
<WrappedRoute path='/settings/mutes' exact page={SettingsPage} component={Mutes} content={children} componentParams={{ title: 'Muted Accounts' }} />
|
||||||
|
|
||||||
<Redirect from='/@:username' to='/:username' exact />
|
<Redirect from='/@:username' to='/:username' exact />
|
||||||
<WrappedRoute path='/:username' publicRoute exact page={ProfilePage} component={AccountTimeline} content={children} />
|
<WrappedRoute path='/:username' publicRoute exact page={ProfilePage} component={AccountTimeline} content={children} />
|
||||||
|
|
||||||
{ /*
|
|
||||||
<Redirect from='/@:username/comments' to='/:username/comments' />
|
<Redirect from='/@:username/comments' to='/:username/comments' />
|
||||||
<WrappedRoute path='/:username/comments' page={ProfilePage} component={AccountTimeline} content={children} componentParams={{ commentsOnly: true }} />
|
<WrappedRoute path='/:username/comments' page={ProfilePage} component={AccountTimeline} content={children} componentParams={{ commentsOnly: true }} />
|
||||||
*/ }
|
|
||||||
|
|
||||||
<Redirect from='/@:username/followers' to='/:username/followers' />
|
<Redirect from='/@:username/followers' to='/:username/followers' />
|
||||||
<WrappedRoute path='/:username/followers' page={ProfilePage} component={Followers} content={children} />
|
<WrappedRoute path='/:username/followers' page={ProfilePage} component={Followers} content={children} />
|
||||||
@ -195,8 +196,8 @@ class SwitchingArea extends PureComponent {
|
|||||||
<Redirect from='/@:username/media' to='/:username/media' />
|
<Redirect from='/@:username/media' to='/:username/media' />
|
||||||
<WrappedRoute path='/:username/media' page={ProfilePage} component={AccountGallery} content={children} />
|
<WrappedRoute path='/:username/media' page={ProfilePage} component={AccountGallery} content={children} />
|
||||||
|
|
||||||
<Redirect from='/@:username/favorites' to='/:username/favorites' />
|
<Redirect from='/@:username/likes' to='/:username/likes' />
|
||||||
<WrappedRoute path='/:username/favorites' page={ProfilePage} component={FavoritedStatuses} content={children} />
|
<WrappedRoute path='/:username/likes' page={ProfilePage} component={LikedStatuses} content={children} />
|
||||||
|
|
||||||
<Redirect from='/@:username/posts/:statusId' to='/:username/posts/:statusId' exact />
|
<Redirect from='/@:username/posts/:statusId' to='/:username/posts/:statusId' exact />
|
||||||
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact page={BasicPage} component={Status} content={children} componentParams={{ title: 'Status' }} />
|
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact page={BasicPage} component={Status} content={children} componentParams={{ title: 'Status' }} />
|
||||||
@ -489,15 +490,15 @@ class UI extends PureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={this.setRef}>
|
<div ref={this.setRef}>
|
||||||
<SwitchingArea
|
<LoadingBarContainer className={[_s.height1PX, _s.z3, _s.backgroundColorBrandLight].join(' ')} />
|
||||||
location={location}
|
|
||||||
onLayoutChange={this.handleLayoutChange}
|
<SwitchingArea location={location} onLayoutChange={this.handleLayoutChange}>
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</SwitchingArea>
|
</SwitchingArea>
|
||||||
|
|
||||||
<ModalRoot />
|
<ModalRoot />
|
||||||
<PopoverRoot />
|
<PopoverRoot />
|
||||||
|
|
||||||
<UploadArea active={draggingOver} onClose={this.closeUploadModal} />
|
<UploadArea active={draggingOver} onClose={this.closeUploadModal} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
@ -42,8 +42,8 @@ export function FollowRequests() {
|
|||||||
return import(/* webpackChunkName: "features/follow_requests" */'../../follow_requests')
|
return import(/* webpackChunkName: "features/follow_requests" */'../../follow_requests')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FavoritedStatuses() {
|
export function LikedStatuses() {
|
||||||
return import(/* webpackChunkName: "features/favorited_statuses" */'../../favorited_statuses')
|
return import(/* webpackChunkName: "features/liked_statuses" */'../../liked_statuses')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function GenericNotFound() {
|
export function GenericNotFound() {
|
||||||
|
50
app/javascript/gabsocial/layouts/settings_layout.js
Normal file
50
app/javascript/gabsocial/layouts/settings_layout.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import Sticky from 'react-stickynode'
|
||||||
|
import Search from '../components/search'
|
||||||
|
import ColumnHeader from '../components/column_header'
|
||||||
|
import Sidebar from '../components/sidebar'
|
||||||
|
|
||||||
|
export default class SettingsLayout extends PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
actions: PropTypes.array,
|
||||||
|
tabs: PropTypes.array,
|
||||||
|
title: PropTypes.string,
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { children, actions, tabs, title } = this.props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={[_s.default, _s.flexRow, _s.width100PC, _s.heightMin100VH, _s.backgroundColorSecondary3].join(' ')}>
|
||||||
|
|
||||||
|
<Sidebar />
|
||||||
|
|
||||||
|
<main role='main' className={[_s.default, _s.flexShrink1, _s.flexGrow1, _s.borderColorSecondary2, _s.borderLeft1PX].join(' ')}>
|
||||||
|
|
||||||
|
<div className={[_s.default, _s.height53PX, _s.borderBottom1PX, _s.borderColorSecondary2, _s.backgroundColorSecondary3, _s.z3, _s.top0, _s.positionFixed].join(' ')}>
|
||||||
|
<div className={[_s.default, _s.height53PX, _s.pl15, _s.width1015PX, _s.flexRow, _s.justifyContentSpaceBetween].join(' ')}>
|
||||||
|
<div className={[_s.default, _s.width100PC].join(' ')}>
|
||||||
|
<ColumnHeader
|
||||||
|
title={title}
|
||||||
|
showBackBtn={true}
|
||||||
|
actions={actions}
|
||||||
|
tabs={tabs}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={[_s.default, _s.height53PX].join(' ')}></div>
|
||||||
|
|
||||||
|
<div className={[_s.default, _s.width1015PX, _s.flexRow, _s.justifyContentSpaceBetween, _s.pl15, _s.py15].join(' ')}>
|
||||||
|
<div className={[_s.default, _s.z1, _s.width100PC].join(' ')}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { Fragment } from 'react'
|
import { Fragment } from 'react'
|
||||||
|
import { openModal } from '../actions/modal'
|
||||||
import GroupSidebarPanel from '../components/panel/groups_panel'
|
import GroupSidebarPanel from '../components/panel/groups_panel'
|
||||||
import LinkFooter from '../components/link_footer'
|
import LinkFooter from '../components/link_footer'
|
||||||
import WhoToFollowPanel from '../components/panel/who_to_follow_panel'
|
import WhoToFollowPanel from '../components/panel/who_to_follow_panel'
|
||||||
@ -10,18 +11,26 @@ import DefaultLayout from '../layouts/default_layout'
|
|||||||
import TimelineComposeBlock from '../components/timeline_compose_block'
|
import TimelineComposeBlock from '../components/timeline_compose_block'
|
||||||
import Divider from '../components/divider'
|
import Divider from '../components/divider'
|
||||||
|
|
||||||
export default class HomePage extends PureComponent {
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
onOpenHomePageSettingsModal() {
|
||||||
|
dispatch(openModal('HOME_TIMELINE_SETTINGS'))
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default
|
||||||
|
@connect(null, mapDispatchToProps)
|
||||||
|
class HomePage extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
onOpenHomePageSettingsModal: PropTypes.func.isRequired,
|
||||||
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
document.title = '(1) Home - Gab'
|
document.title = '(1) Home - Gab'
|
||||||
}
|
}
|
||||||
|
|
||||||
handleEditHomeTimeline () {
|
|
||||||
console.log("handleEditHomeTimeline")
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children } = this.props
|
const { children, onOpenHomePageSettingsModal } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DefaultLayout
|
<DefaultLayout
|
||||||
@ -29,7 +38,7 @@ export default class HomePage extends PureComponent {
|
|||||||
actions={[
|
actions={[
|
||||||
{
|
{
|
||||||
icon: 'ellipsis',
|
icon: 'ellipsis',
|
||||||
onClick: this.handleEditHomeTimeline
|
onClick: onOpenHomePageSettingsModal,
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
layout={(
|
layout={(
|
||||||
|
@ -13,13 +13,13 @@ export default class SearchPage extends PureComponent {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<SearchLayout
|
<SearchLayout
|
||||||
|
showBackBtn
|
||||||
layout={(
|
layout={(
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<SearchFilterPanel />
|
<SearchFilterPanel />
|
||||||
<LinkFooter />
|
<LinkFooter />
|
||||||
</Fragment>
|
</Fragment>
|
||||||
)}
|
)}
|
||||||
showBackBtn
|
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</SearchLayout>
|
</SearchLayout>
|
||||||
|
@ -1,12 +1,22 @@
|
|||||||
|
import SettingsLayout from '../layouts/settings_layout'
|
||||||
|
|
||||||
export default class SettingsPage extends PureComponent {
|
export default class SettingsPage extends PureComponent {
|
||||||
|
|
||||||
|
static propTypes = {
|
||||||
|
tabs: PropTypes.array,
|
||||||
|
title: PropTypes.string,
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { children } = this.props;
|
const { children, title, tabs } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<SettingsLayout
|
||||||
|
title={title}
|
||||||
|
tabs={tabs}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</SettingsLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,7 +2,6 @@ import Immutable from 'immutable';
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
MUTES_INIT_MODAL,
|
MUTES_INIT_MODAL,
|
||||||
MUTES_TOGGLE_HIDE_NOTIFICATIONS,
|
|
||||||
} from '../actions/mutes';
|
} from '../actions/mutes';
|
||||||
|
|
||||||
const initialState = Immutable.Map({
|
const initialState = Immutable.Map({
|
||||||
@ -21,8 +20,6 @@ export default function mutes(state = initialState, action) {
|
|||||||
state.setIn(['new', 'account'], action.account);
|
state.setIn(['new', 'account'], action.account);
|
||||||
state.setIn(['new', 'notifications'], true);
|
state.setIn(['new', 'notifications'], true);
|
||||||
});
|
});
|
||||||
case MUTES_TOGGLE_HIDE_NOTIFICATIONS:
|
|
||||||
return state.updateIn(['new', 'notifications'], (old) => !old);
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -220,6 +220,10 @@ body {
|
|||||||
margin: auto;
|
margin: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.margin1PX {
|
||||||
|
margin: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
.displayNone {
|
.displayNone {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -428,6 +432,10 @@ body {
|
|||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.heightMax80VH {
|
||||||
|
max-height: 80vh;
|
||||||
|
}
|
||||||
|
|
||||||
.heightMin50VH {
|
.heightMin50VH {
|
||||||
min-height: 50vh;
|
min-height: 50vh;
|
||||||
}
|
}
|
||||||
@ -440,14 +448,26 @@ body {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.height24PX {
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.height22PX {
|
.height22PX {
|
||||||
height: 22px;
|
height: 22px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.height20PX {
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.height4PX {
|
.height4PX {
|
||||||
height: 4px;
|
height: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.height1PX {
|
||||||
|
height: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
.height50PX {
|
.height50PX {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
}
|
}
|
||||||
@ -496,6 +516,10 @@ body {
|
|||||||
width: 330px;
|
width: 330px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.width250PX {
|
||||||
|
width: 240px;
|
||||||
|
}
|
||||||
|
|
||||||
.width240PX {
|
.width240PX {
|
||||||
width: 240px;
|
width: 240px;
|
||||||
}
|
}
|
||||||
@ -504,6 +528,14 @@ body {
|
|||||||
width: 72px;
|
width: 72px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.width50PX {
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.width20PX {
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.width100PC {
|
.width100PC {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@ -933,3 +965,7 @@ body {
|
|||||||
display: block;
|
display: block;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
} */
|
} */
|
||||||
|
|
||||||
|
.visibilityHidden {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
@ -75,7 +75,6 @@
|
|||||||
"@babel/preset-react": "^7.0.0",
|
"@babel/preset-react": "^7.0.0",
|
||||||
"@babel/runtime": "^7.3.4",
|
"@babel/runtime": "^7.3.4",
|
||||||
"@clusterws/cws": "^0.14.0",
|
"@clusterws/cws": "^0.14.0",
|
||||||
"@storybook/react": "^5.3.14",
|
|
||||||
"array-includes": "^3.0.3",
|
"array-includes": "^3.0.3",
|
||||||
"autoprefixer": "^9.5.1",
|
"autoprefixer": "^9.5.1",
|
||||||
"axios": "^0.19.0",
|
"axios": "^0.19.0",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user