Progress
This commit is contained in:
@@ -1 +1 @@
|
||||
export { default } from './media_item';
|
||||
export { default } from './media_item'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './account_gallery';
|
||||
export { default } from './account_gallery'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './header';
|
||||
export { default } from './header'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './inner_header';
|
||||
export { default } from './inner_header'
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default } from './moved_note';
|
||||
export { default } from './moved_note'
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default } from './profile_info_panel';
|
||||
export { default } from './profile_info_panel'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './account_timeline';
|
||||
export { default } from './account_timeline'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './blocks';
|
||||
export { default } from './blocks'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './column_settings';
|
||||
export { default } from './column_settings'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './community_timeline';
|
||||
export { default } from './community_timeline'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './action_bar';
|
||||
export { default } from './action_bar'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './character_counter';
|
||||
export { default } from './character_counter'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './compose_form';
|
||||
export { default } from './compose_form'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './emoji_picker_dropdown';
|
||||
export { default } from './emoji_picker_dropdown'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './navigation_bar';
|
||||
export { default } from './navigation_bar'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './poll_form';
|
||||
export { default } from './poll_form'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './reply_indicator';
|
||||
export { default } from './reply_indicator'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './search_results';
|
||||
export { default } from './search_results'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './upload';
|
||||
export { default } from './upload'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './upload_form';
|
||||
export { default } from './upload_form'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './upload_progress';
|
||||
export { default } from './upload_progress'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './warning';
|
||||
export { default } from './warning'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './compose';
|
||||
export { default } from './compose'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './domain_blocks';
|
||||
export { default } from './domain_blocks'
|
||||
@@ -2,7 +2,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { debounce } from 'lodash';
|
||||
import { fetchFavoritedStatuses, expandFavoritedStatuses } from '../../actions/favourites';
|
||||
import { fetchFavoritedStatuses, expandFavoritedStatuses } from '../../actions/favorites';
|
||||
import { meUsername } from '../../initial_state';
|
||||
import StatusList from '../../components/status_list';
|
||||
import ColumnIndicator from '../../components/column_indicator';
|
||||
@@ -10,15 +10,15 @@ import ColumnIndicator from '../../components/column_indicator';
|
||||
const mapStateToProps = (state, { params: { username } }) => {
|
||||
return {
|
||||
isMyAccount: (username.toLowerCase() === meUsername.toLowerCase()),
|
||||
statusIds: state.getIn(['status_lists', 'favourites', 'items']),
|
||||
isLoading: state.getIn(['status_lists', 'favourites', 'isLoading'], true),
|
||||
hasMore: !!state.getIn(['status_lists', 'favourites', 'next']),
|
||||
statusIds: state.getIn(['status_lists', 'favorites', 'items']),
|
||||
isLoading: state.getIn(['status_lists', 'favorites', 'isLoading'], true),
|
||||
hasMore: !!state.getIn(['status_lists', 'favorites', 'next']),
|
||||
};
|
||||
};
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
class Favourites extends ImmutablePureComponent {
|
||||
class Favorites extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
@@ -46,11 +46,11 @@ class Favourites extends ImmutablePureComponent {
|
||||
return (
|
||||
<StatusList
|
||||
statusIds={statusIds}
|
||||
scrollKey='favourited_statuses'
|
||||
scrollKey='favorited_statuses'
|
||||
hasMore={hasMore}
|
||||
isLoading={isLoading}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={<FormattedMessage id='empty_column.favourited_statuses' defaultMessage="You don't have any favourite gabs yet. When you favourite one, it will show up here." />}
|
||||
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." />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './favorited_statuses'
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from './favourited_statuses';
|
||||
@@ -1 +1 @@
|
||||
export { default } from './account_authorize';
|
||||
export { default } from './account_authorize'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './follow_requests';
|
||||
export { default } from './follow_requests'
|
||||
@@ -1,34 +1,36 @@
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { debounce } from 'lodash';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import ColumnIndicator from '../../components/column_indicator';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { debounce } from 'lodash'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import ColumnIndicator from '../../components/column_indicator'
|
||||
import {
|
||||
fetchAccount,
|
||||
fetchFollowers,
|
||||
expandFollowers,
|
||||
fetchAccountByUsername,
|
||||
} from '../../actions/accounts';
|
||||
import { me } from '../../initial_state';
|
||||
import AccountContainer from '../../containers/account_container';
|
||||
import ScrollableList from '../../components/scrollable_list';
|
||||
} from '../../actions/accounts'
|
||||
import { me } from '../../initial_state'
|
||||
import AccountContainer from '../../containers/account_container'
|
||||
import ScrollableList from '../../components/scrollable_list'
|
||||
import Block from '../../components/block'
|
||||
import Heading from '../../components/heading'
|
||||
|
||||
const mapStateToProps = (state, { params: { username } }) => {
|
||||
const accounts = state.getIn(['accounts']);
|
||||
const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() == username.toLowerCase());
|
||||
const accounts = state.getIn(['accounts'])
|
||||
const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() == username.toLowerCase())
|
||||
|
||||
let accountId = -1;
|
||||
let accountId = -1
|
||||
if (accountFetchError) {
|
||||
accountId = null;
|
||||
accountId = null
|
||||
} else {
|
||||
let account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase());
|
||||
accountId = account ? account.getIn(['id'], null) : -1;
|
||||
let account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase())
|
||||
accountId = account ? account.getIn(['id'], null) : -1
|
||||
}
|
||||
|
||||
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false);
|
||||
const isLocked = state.getIn(['accounts', accountId, 'locked'], false);
|
||||
const isFollowing = state.getIn(['relationships', accountId, 'following'], false);
|
||||
const unavailable = (me == accountId) ? false : (isBlocked || (isLocked && !isFollowing));
|
||||
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false)
|
||||
const isLocked = state.getIn(['accounts', accountId, 'locked'], false)
|
||||
const isFollowing = state.getIn(['relationships', accountId, 'following'], false)
|
||||
const unavailable = (me == accountId) ? false : (isBlocked || (isLocked && !isFollowing))
|
||||
|
||||
return {
|
||||
accountId,
|
||||
@@ -36,69 +38,93 @@ const mapStateToProps = (state, { params: { username } }) => {
|
||||
isAccount: !!state.getIn(['accounts', accountId]),
|
||||
accountIds: state.getIn(['user_lists', 'followers', accountId, 'items']),
|
||||
hasMore: !!state.getIn(['user_lists', 'followers', accountId, 'next']),
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const messages = defineMessages({
|
||||
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
||||
empty: { id: 'account.followers.empty', defaultMessage: 'No one follows this user yet.' },
|
||||
unavailable: { id: 'empty_column.account_unavailable', defaultMessage: 'Profile unavailable' },
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class Followers extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
hasMore: PropTypes.bool,
|
||||
isAccount: PropTypes.bool,
|
||||
unavailable: PropTypes.bool,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
const { params: { username }, accountId } = this.props;
|
||||
const { params: { username }, accountId } = this.props
|
||||
|
||||
if (accountId && accountId !== -1) {
|
||||
this.props.dispatch(fetchAccount(accountId));
|
||||
this.props.dispatch(fetchFollowers(accountId));
|
||||
this.props.dispatch(fetchAccount(accountId))
|
||||
this.props.dispatch(fetchFollowers(accountId))
|
||||
} else {
|
||||
this.props.dispatch(fetchAccountByUsername(username));
|
||||
this.props.dispatch(fetchAccountByUsername(username))
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.accountId && nextProps.accountId !== -1 && (nextProps.accountId !== this.props.accountId && nextProps.accountId)) {
|
||||
this.props.dispatch(fetchAccount(nextProps.accountId));
|
||||
this.props.dispatch(fetchFollowers(nextProps.accountId));
|
||||
this.props.dispatch(fetchAccount(nextProps.accountId))
|
||||
this.props.dispatch(fetchFollowers(nextProps.accountId))
|
||||
}
|
||||
}
|
||||
|
||||
handleLoadMore = debounce(() => {
|
||||
if (this.props.accountId && this.props.accountId !== -1) {
|
||||
this.props.dispatch(expandFollowers(this.props.accountId));
|
||||
this.props.dispatch(expandFollowers(this.props.accountId))
|
||||
}
|
||||
}, 300, { leading: true });
|
||||
}, 300, { leading: true })
|
||||
|
||||
render() {
|
||||
const { accountIds, hasMore, isAccount, accountId, unavailable } = this.props;
|
||||
const {
|
||||
accountIds,
|
||||
hasMore,
|
||||
isAccount,
|
||||
accountId,
|
||||
unavailable,
|
||||
intl
|
||||
} = this.props
|
||||
|
||||
if (!isAccount && accountId !== -1) {
|
||||
return (<ColumnIndicator type='missing' />);
|
||||
return <ColumnIndicator type='missing' />
|
||||
} else if (accountId === -1 || (!accountIds)) {
|
||||
return (<ColumnIndicator type='loading' />);
|
||||
return <ColumnIndicator type='loading' />
|
||||
} else if (unavailable) {
|
||||
return (<ColumnIndicator type='error' message={<FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' />} />);
|
||||
return <ColumnIndicator type='error' message={intl.formatMessage(messages.unavailable)} />
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollableList
|
||||
scrollKey='followers'
|
||||
hasMore={hasMore}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={<FormattedMessage id='account.followers.empty' defaultMessage='No one follows this user yet.' />}
|
||||
>
|
||||
{accountIds.map(id =>
|
||||
<AccountContainer key={id} id={id} withNote={false} />
|
||||
)}
|
||||
</ScrollableList>
|
||||
);
|
||||
<Block>
|
||||
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX, _s.justifyContentCenter, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')}>
|
||||
<Heading size='h3'>
|
||||
{intl.formatMessage(messages.followers)}
|
||||
</Heading>
|
||||
</div>
|
||||
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX].join(' ')}>
|
||||
<ScrollableList
|
||||
scrollKey='followers'
|
||||
hasMore={hasMore}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={intl.formatMessage(messages.empty)}
|
||||
>
|
||||
{accountIds.map((id, i) => (
|
||||
<AccountContainer key={id} id={id} withNote={false} compact />
|
||||
))}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
</Block>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default } from './followers';
|
||||
export { default } from './followers'
|
||||
@@ -1,34 +1,36 @@
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { debounce } from 'lodash';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { debounce } from 'lodash'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import {
|
||||
fetchAccount,
|
||||
fetchFollowing,
|
||||
expandFollowing,
|
||||
fetchAccountByUsername,
|
||||
} from '../../actions/accounts';
|
||||
import { me } from '../../initial_state';
|
||||
import AccountContainer from '../../containers/account_container';
|
||||
import ColumnIndicator from '../../components/column_indicator';
|
||||
import ScrollableList from '../../components/scrollable_list';
|
||||
} from '../../actions/accounts'
|
||||
import { me } from '../../initial_state'
|
||||
import AccountContainer from '../../containers/account_container'
|
||||
import ColumnIndicator from '../../components/column_indicator'
|
||||
import ScrollableList from '../../components/scrollable_list'
|
||||
import Block from '../../components/block'
|
||||
import Heading from '../../components/heading'
|
||||
|
||||
const mapStateToProps = (state, { params: { username } }) => {
|
||||
const accounts = state.getIn(['accounts']);
|
||||
const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() == username.toLowerCase());
|
||||
const accounts = state.getIn(['accounts'])
|
||||
const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() == username.toLowerCase())
|
||||
|
||||
let accountId = -1;
|
||||
let accountId = -1
|
||||
if (accountFetchError) {
|
||||
accountId = null;
|
||||
accountId = null
|
||||
} else {
|
||||
let account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase());
|
||||
accountId = account ? account.getIn(['id'], null) : -1;
|
||||
let account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase())
|
||||
accountId = account ? account.getIn(['id'], null) : -1
|
||||
}
|
||||
|
||||
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false);
|
||||
const isLocked = state.getIn(['accounts', accountId, 'locked'], false);
|
||||
const isFollowing = state.getIn(['relationships', accountId, 'following'], false);
|
||||
const unavailable = (me == accountId) ? false : (isBlocked || (isLocked && !isFollowing));
|
||||
const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false)
|
||||
const isLocked = state.getIn(['accounts', accountId, 'locked'], false)
|
||||
const isFollowing = state.getIn(['relationships', accountId, 'following'], false)
|
||||
const unavailable = (me == accountId) ? false : (isBlocked || (isLocked && !isFollowing))
|
||||
|
||||
return {
|
||||
accountId,
|
||||
@@ -36,71 +38,93 @@ const mapStateToProps = (state, { params: { username } }) => {
|
||||
isAccount: !!state.getIn(['accounts', accountId]),
|
||||
accountIds: state.getIn(['user_lists', 'following', accountId, 'items']),
|
||||
hasMore: !!state.getIn(['user_lists', 'following', accountId, 'next']),
|
||||
};
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
const messages = defineMessages({
|
||||
follows: { id: 'account.follows', defaultMessage: 'Follows' },
|
||||
empty: { id: 'account.follows.empty', defaultMessage: 'This user doesn\'t follow anyone yet.' },
|
||||
unavailable: { id: 'empty_column.account_unavailable', defaultMessage: 'Profile unavailable' },
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class Following extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
hasMore: PropTypes.bool,
|
||||
isAccount: PropTypes.bool,
|
||||
unavailable: PropTypes.bool,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
const { params: { username }, accountId } = this.props;
|
||||
componentWillMount() {
|
||||
const { params: { username }, accountId } = this.props
|
||||
|
||||
if (accountId && accountId !== -1) {
|
||||
this.props.dispatch(fetchAccount(accountId));
|
||||
this.props.dispatch(fetchFollowing(accountId));
|
||||
this.props.dispatch(fetchAccount(accountId))
|
||||
this.props.dispatch(fetchFollowing(accountId))
|
||||
} else {
|
||||
this.props.dispatch(fetchAccountByUsername(username));
|
||||
this.props.dispatch(fetchAccountByUsername(username))
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.accountId && nextProps.accountId !== -1 && (nextProps.accountId !== this.props.accountId && nextProps.accountId)) {
|
||||
this.props.dispatch(fetchAccount(nextProps.accountId));
|
||||
this.props.dispatch(fetchFollowing(nextProps.accountId));
|
||||
this.props.dispatch(fetchAccount(nextProps.accountId))
|
||||
this.props.dispatch(fetchFollowing(nextProps.accountId))
|
||||
}
|
||||
}
|
||||
|
||||
handleLoadMore = debounce(() => {
|
||||
if (this.props.accountId && this.props.accountId !== -1) {
|
||||
this.props.dispatch(expandFollowing(this.props.accountId));
|
||||
this.props.dispatch(expandFollowing(this.props.accountId))
|
||||
}
|
||||
}, 300, { leading: true });
|
||||
}, 300, { leading: true })
|
||||
|
||||
render () {
|
||||
const { accountIds, hasMore, isAccount, accountId, unavailable } = this.props;
|
||||
render() {
|
||||
const {
|
||||
accountIds,
|
||||
hasMore,
|
||||
isAccount,
|
||||
accountId,
|
||||
unavailable,
|
||||
intl
|
||||
} = this.props
|
||||
|
||||
if (!isAccount && accountId !== -1) {
|
||||
return ( <ColumnIndicator type='missing' /> );
|
||||
return <ColumnIndicator type='missing' />
|
||||
} else if (accountId === -1 || (!accountIds)) {
|
||||
return ( <ColumnIndicator type='loading' /> );
|
||||
return <ColumnIndicator type='loading' />
|
||||
} else if (unavailable) {
|
||||
return (<ColumnIndicator type='error' message={<FormattedMessage id='empty_column.account_unavailable' defaultMessage='Profile unavailable' />} />);
|
||||
return <ColumnIndicator type='error' message={intl.formatMessage(messages.unavailable)} />
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollableList
|
||||
scrollKey='following'
|
||||
hasMore={hasMore}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={<FormattedMessage id='account.follows.empty' defaultMessage="This user doesn't follow anyone yet." />}
|
||||
>
|
||||
{accountIds.map(id =>
|
||||
<AccountContainer key={id} id={id} withNote={false} />
|
||||
)}
|
||||
</ScrollableList>
|
||||
);
|
||||
<Block>
|
||||
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX, _s.justifyContentCenter, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')}>
|
||||
<Heading size='h3'>
|
||||
{intl.formatMessage(messages.follows)}
|
||||
</Heading>
|
||||
</div>
|
||||
<div className={[_s.default, _s.paddingHorizontal15PX, _s.paddingVertical10PX].join(' ')}>
|
||||
<ScrollableList
|
||||
scrollKey='following'
|
||||
hasMore={hasMore}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={intl.formatMessage(messages.empty)}
|
||||
>
|
||||
{accountIds.map((id, i) => (
|
||||
<AccountContainer key={id} id={id} withNote={false} compact />
|
||||
))}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
</Block>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
export { default } from './following';
|
||||
export { default } from './following'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './generic_not_found';
|
||||
export { default } from './generic_not_found'
|
||||
@@ -1,7 +1,9 @@
|
||||
import { changeValue, submit, reset } from '../../../actions/group_editor';
|
||||
import Icon from '../../../components/icon';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import classNames from 'classnames';
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { changeValue, submit, reset } from '../../actions/group_editor'
|
||||
import Block from '../../components/block'
|
||||
import Button from '../../components/button'
|
||||
import Icon from '../../components/icon'
|
||||
import Input from '../../components/icon'
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'groups.form.title', defaultMessage: 'Enter a new group title' },
|
||||
@@ -9,14 +11,14 @@ const messages = defineMessages({
|
||||
coverImage: { id: 'groups.form.coverImage', defaultMessage: 'Upload a banner image' },
|
||||
coverImageChange: { id: 'groups.form.coverImageChange', defaultMessage: 'Banner image selected' },
|
||||
create: { id: 'groups.form.create', defaultMessage: 'Create group' },
|
||||
});
|
||||
})
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
title: state.getIn(['group_editor', 'title']),
|
||||
description: state.getIn(['group_editor', 'description']),
|
||||
coverImage: state.getIn(['group_editor', 'coverImage']),
|
||||
disabled: state.getIn(['group_editor', 'isSubmitting']),
|
||||
});
|
||||
})
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onTitleChange: value => dispatch(changeValue('title', value)),
|
||||
@@ -24,7 +26,7 @@ const mapDispatchToProps = dispatch => ({
|
||||
onCoverImageChange: value => dispatch(changeValue('coverImage', value)),
|
||||
onSubmit: routerHistory => dispatch(submit(routerHistory)),
|
||||
reset: () => dispatch(reset()),
|
||||
});
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@@ -43,69 +45,70 @@ class Create extends PureComponent {
|
||||
intl: PropTypes.object.isRequired,
|
||||
onTitleChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
this.props.reset();
|
||||
this.props.reset()
|
||||
}
|
||||
|
||||
handleTitleChange = e => {
|
||||
this.props.onTitleChange(e.target.value);
|
||||
this.props.onTitleChange(e.target.value)
|
||||
}
|
||||
|
||||
handleDescriptionChange = e => {
|
||||
this.props.onDescriptionChange(e.target.value);
|
||||
this.props.onDescriptionChange(e.target.value)
|
||||
}
|
||||
|
||||
handleCoverImageChange = e => {
|
||||
this.props.onCoverImageChange(e.target.files[0]);
|
||||
this.props.onCoverImageChange(e.target.files[0])
|
||||
}
|
||||
|
||||
handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
this.props.onSubmit(this.context.router.history);
|
||||
e.preventDefault()
|
||||
this.props.onSubmit(this.context.router.history)
|
||||
}
|
||||
|
||||
render () {
|
||||
const { title, description, coverImage, disabled, intl } = this.props;
|
||||
render() {
|
||||
const { title, description, coverImage, disabled, intl } = this.props
|
||||
|
||||
return (
|
||||
<form className='group-form' onSubmit={this.handleSubmit}>
|
||||
<div>
|
||||
<input
|
||||
className='standard'
|
||||
type='text'
|
||||
value={title}
|
||||
disabled={disabled}
|
||||
onChange={this.handleTitleChange}
|
||||
placeholder={intl.formatMessage(messages.title)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<textarea
|
||||
className='standard'
|
||||
type='text'
|
||||
value={description}
|
||||
disabled={disabled}
|
||||
onChange={this.handleDescriptionChange}
|
||||
placeholder={intl.formatMessage(messages.description)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='group_cover_image' className={classNames('group-form__file-label', { 'group-form__file-label--selected': coverImage !== null })}>
|
||||
{intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
|
||||
</label>
|
||||
<input
|
||||
type='file'
|
||||
className='group-form__file'
|
||||
id='group_cover_image'
|
||||
disabled={disabled}
|
||||
onChange={this.handleCoverImageChange}
|
||||
/>
|
||||
<button className='button'>{intl.formatMessage(messages.create)}</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
<Block>
|
||||
<form className='group-form' onSubmit={this.handleSubmit}>
|
||||
<div>
|
||||
<Input
|
||||
type='text'
|
||||
value={title}
|
||||
disabled={disabled}
|
||||
onChange={this.handleTitleChange}
|
||||
placeholder={intl.formatMessage(messages.title)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<textarea
|
||||
className='standard'
|
||||
type='text'
|
||||
value={description}
|
||||
disabled={disabled}
|
||||
onChange={this.handleDescriptionChange}
|
||||
placeholder={intl.formatMessage(messages.description)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor='group_cover_image' className='group-form__file-label--selected'>
|
||||
{intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
|
||||
</label>
|
||||
<input
|
||||
type='file'
|
||||
className='group-form__file'
|
||||
id='group_cover_image'
|
||||
disabled={disabled}
|
||||
onChange={this.handleCoverImageChange}
|
||||
/>
|
||||
<button className='button'>{intl.formatMessage(messages.create)}</button>
|
||||
</div>
|
||||
</form>
|
||||
</Block>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
1
app/javascript/gabsocial/features/group_create/index.js
Normal file
1
app/javascript/gabsocial/features/group_create/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './group_create'
|
||||
@@ -0,0 +1,83 @@
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { debounce } from 'lodash';
|
||||
import {
|
||||
fetchMembers,
|
||||
expandMembers,
|
||||
updateRole,
|
||||
createRemovedAccount,
|
||||
} from '../../actions/groups';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import AccountContainer from '../../containers/account_container';
|
||||
import ScrollableList from '../../components/scrollable_list';
|
||||
|
||||
const mapStateToProps = (state, { params: { id } }) => ({
|
||||
group: state.getIn(['groups', id]),
|
||||
relationships: state.getIn(['group_relationships', id]),
|
||||
accountIds: state.getIn(['user_lists', 'groups', id, 'items']),
|
||||
hasMore: !!state.getIn(['user_lists', 'groups', id, 'next']),
|
||||
});
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
class GroupMembers extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
hasMore: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
const { params: { id } } = this.props;
|
||||
|
||||
this.props.dispatch(fetchMembers(id));
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.params.id !== this.props.params.id) {
|
||||
this.props.dispatch(fetchMembers(nextProps.params.id));
|
||||
}
|
||||
}
|
||||
|
||||
handleLoadMore = debounce(() => {
|
||||
this.props.dispatch(expandMembers(this.props.params.id));
|
||||
}, 300, { leading: true });
|
||||
|
||||
render() {
|
||||
const { accountIds, hasMore, group, relationships, dispatch } = this.props;
|
||||
|
||||
if (!group || !accountIds || !relationships) {
|
||||
return <LoadingIndicator />
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollableList
|
||||
scrollKey='members'
|
||||
hasMore={hasMore}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={<FormattedMessage id='group.members.empty' defaultMessage='This group does not has any members.' />}
|
||||
>
|
||||
{accountIds.map(id => {
|
||||
let menu = [];
|
||||
|
||||
if (relationships.get('admin')) {
|
||||
menu = [
|
||||
{ text: 'Remove from group', action: () => dispatch(createRemovedAccount(group.get('id'), id)) },
|
||||
{ text: 'Make administrator', action: () => dispatch(updateRole(group.get('id'), id, 'admin')) },
|
||||
]
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="group-account-wrapper" key={id}>
|
||||
<AccountContainer id={id} withNote={false} actionIcon="none" onActionClick={() => true} />
|
||||
{menu.length > 0 && <DropdownMenuContainer items={menu} icon='ellipsis-h' size={18} direction='right' />}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</ScrollableList>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
1
app/javascript/gabsocial/features/group_members/index.js
Normal file
1
app/javascript/gabsocial/features/group_members/index.js
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './group_members'
|
||||
@@ -1,15 +1,15 @@
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { debounce } from 'lodash';
|
||||
import ColumnIndicator from '../../../components/column_indicator';
|
||||
import ColumnIndicator from '../../components/column_indicator';
|
||||
import {
|
||||
fetchRemovedAccounts,
|
||||
expandRemovedAccounts,
|
||||
removeRemovedAccount,
|
||||
} from '../../../actions/groups';
|
||||
} from '../../actions/groups';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import AccountContainer from '../../../containers/account_container';
|
||||
import ScrollableList from '../../../components/scrollable_list';
|
||||
import AccountContainer from '../../containers/account_container';
|
||||
import ScrollableList from '../../components/scrollable_list';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
const messages = defineMessages({
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from './group_removed_accounts'
|
||||
@@ -1,105 +1,98 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { Link } from 'react-router-dom';
|
||||
import classNames from 'classnames';
|
||||
import { fetchGroups } from '../../../actions/groups';
|
||||
import { openModal } from '../../../actions/modal';
|
||||
import { me } from '../../../initial_state';
|
||||
import GroupCard from './card';
|
||||
import GroupCreate from '../create';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { Link } from 'react-router-dom'
|
||||
import classNames from 'classnames'
|
||||
import { connectGroupStream } from '../../actions/streaming'
|
||||
import { expandGroupTimeline } from '../../actions/timelines'
|
||||
import StatusListContainer from '../../containers/status_list_container'
|
||||
// import ColumnSettingsContainer from './containers/column_settings_container'
|
||||
import ColumnIndicator from '../../components/column_indicator'
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.groups', defaultMessage: 'Groups' },
|
||||
create: { id: 'groups.create', defaultMessage: 'Create group' },
|
||||
tab_featured: { id: 'groups.tab_featured', defaultMessage: 'Featured' },
|
||||
tab_member: { id: 'groups.tab_member', defaultMessage: 'Member' },
|
||||
tab_admin: { id: 'groups.tab_admin', defaultMessage: 'Manage' },
|
||||
});
|
||||
tabLatest: { id: 'group.timeline.tab_latest', defaultMessage: 'Latest' },
|
||||
show: { id: 'group.timeline.show_settings', defaultMessage: 'Show settings' },
|
||||
hide: { id: 'group.timeline.hide_settings', defaultMessage: 'Hide settings' },
|
||||
empty: { id: 'empty_column.group', defaultMessage: 'There is nothing in this group yet.\nWhen members of this group post new statuses, they will appear here.' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state, { activeTab }) => ({
|
||||
groupIds: state.getIn(['group_lists', activeTab]),
|
||||
account: state.getIn(['accounts', me]),
|
||||
});
|
||||
const mapStateToProps = (state, props) => ({
|
||||
group: state.getIn(['groups', props.params.id]),
|
||||
relationships: state.getIn(['group_relationships', props.params.id]),
|
||||
hasUnread: state.getIn(['timelines', `group:${props.params.id}`, 'unread']) > 0,
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class Groups extends ImmutablePureComponent {
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
activeTab: PropTypes.string.isRequired,
|
||||
showCreateForm: PropTypes.bool,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
groups: ImmutablePropTypes.map,
|
||||
groupIds: ImmutablePropTypes.list,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
class GroupTimeline extends ImmutablePureComponent {
|
||||
|
||||
componentWillMount () {
|
||||
this.props.dispatch(fetchGroups(this.props.activeTab));
|
||||
static contextTypes = {
|
||||
router: PropTypes.object,
|
||||
}
|
||||
|
||||
componentDidUpdate(oldProps) {
|
||||
if (this.props.activeTab && this.props.activeTab !== oldProps.activeTab) {
|
||||
this.props.dispatch(fetchGroups(this.props.activeTab));
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
columnId: PropTypes.string,
|
||||
hasUnread: PropTypes.bool,
|
||||
group: PropTypes.oneOfType([ImmutablePropTypes.map, PropTypes.bool]),
|
||||
relationships: ImmutablePropTypes.map,
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
state = {
|
||||
collapsed: true,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { dispatch } = this.props
|
||||
const { id } = this.props.params
|
||||
|
||||
dispatch(expandGroupTimeline(id))
|
||||
|
||||
this.disconnect = dispatch(connectGroupStream(id))
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.disconnect) {
|
||||
this.disconnect()
|
||||
this.disconnect = null
|
||||
}
|
||||
}
|
||||
|
||||
handleOpenProUpgradeModal = () => {
|
||||
this.props.dispatch(openModal('PRO_UPGRADE'));
|
||||
handleLoadMore = maxId => {
|
||||
const { id } = this.props.params
|
||||
this.props.dispatch(expandGroupTimeline(id, { maxId }))
|
||||
}
|
||||
|
||||
renderHeader() {
|
||||
const { intl, activeTab, account, onOpenProUpgradeModal } = this.props;
|
||||
handleToggleClick = (e) => {
|
||||
e.stopPropagation()
|
||||
this.setState({ collapsed: !this.state.collapsed })
|
||||
}
|
||||
|
||||
const isPro = account.get('is_pro');
|
||||
render() {
|
||||
const { columnId, group, relationships, account, intl } = this.props
|
||||
const { collapsed } = this.state
|
||||
const { id } = this.props.params
|
||||
|
||||
if (typeof group === 'undefined' || !relationships) {
|
||||
return <ColumnIndicator type='loading' />
|
||||
} else if (group === false) {
|
||||
return <ColumnIndicator type='missing' />
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="group-column-header">
|
||||
<div className="group-column-header__cta">
|
||||
{
|
||||
account && isPro &&
|
||||
<Link to="/groups/create" className="button standard-small">{intl.formatMessage(messages.create)}</Link>
|
||||
}
|
||||
{
|
||||
account && !isPro &&
|
||||
<button onClick={this.handleOpenProUpgradeModal} className="button standard-small">{intl.formatMessage(messages.create)}</button>
|
||||
}
|
||||
</div>
|
||||
<div className="group-column-header__title">{intl.formatMessage(messages.heading)}</div>
|
||||
|
||||
<div className="column-header__wrapper">
|
||||
<h1 className="column-header">
|
||||
<Link to='/groups' className={classNames('btn grouped', {'active': 'featured' === activeTab})}>
|
||||
{intl.formatMessage(messages.tab_featured)}
|
||||
</Link>
|
||||
|
||||
<Link to='/groups/browse/member' className={classNames('btn grouped', {'active': 'member' === activeTab})}>
|
||||
{intl.formatMessage(messages.tab_member)}
|
||||
</Link>
|
||||
|
||||
<Link to='/groups/browse/admin' className={classNames('btn grouped', {'active': 'admin' === activeTab})}>
|
||||
{intl.formatMessage(messages.tab_admin)}
|
||||
</Link>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
<StatusListContainer
|
||||
alwaysPrepend
|
||||
scrollKey={`group_timeline-${columnId}`}
|
||||
timelineId={`group:${id}`}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
group={group}
|
||||
withGroupAdmin={relationships && relationships.get('admin')}
|
||||
emptyMessage={intl.formatMessage(messages.empty)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
render () {
|
||||
const { groupIds, showCreateForm } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{!showCreateForm && this.renderHeader()}
|
||||
{showCreateForm && <GroupCreate /> }
|
||||
|
||||
<div className="group-card-list">
|
||||
{groupIds.map(id => <GroupCard key={id} id={id} />)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default } from './group_timeline';
|
||||
export { default } from './group_timeline'
|
||||
|
||||
@@ -6,27 +6,27 @@ import ColumnIndicator from '../../../components/column_indicator';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'groups.form.title', defaultMessage: 'Title' },
|
||||
description: { id: 'groups.form.description', defaultMessage: 'Description' },
|
||||
coverImage: { id: 'groups.form.coverImage', defaultMessage: 'Upload new banner image (optional)' },
|
||||
coverImageChange: { id: 'groups.form.coverImageChange', defaultMessage: 'Banner image selected' },
|
||||
update: { id: 'groups.form.update', defaultMessage: 'Update group' },
|
||||
title: { id: 'groups.form.title', defaultMessage: 'Title' },
|
||||
description: { id: 'groups.form.description', defaultMessage: 'Description' },
|
||||
coverImage: { id: 'groups.form.coverImage', defaultMessage: 'Upload new banner image (optional)' },
|
||||
coverImageChange: { id: 'groups.form.coverImageChange', defaultMessage: 'Banner image selected' },
|
||||
update: { id: 'groups.form.update', defaultMessage: 'Update group' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
group: state.getIn(['groups', props.params.id]),
|
||||
title: state.getIn(['group_editor', 'title']),
|
||||
description: state.getIn(['group_editor', 'description']),
|
||||
coverImage: state.getIn(['group_editor', 'coverImage']),
|
||||
disabled: state.getIn(['group_editor', 'isSubmitting']),
|
||||
group: state.getIn(['groups', props.params.id]),
|
||||
title: state.getIn(['group_editor', 'title']),
|
||||
description: state.getIn(['group_editor', 'description']),
|
||||
coverImage: state.getIn(['group_editor', 'coverImage']),
|
||||
disabled: state.getIn(['group_editor', 'isSubmitting']),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onTitleChange: value => dispatch(changeValue('title', value)),
|
||||
onDescriptionChange: value => dispatch(changeValue('description', value)),
|
||||
onCoverImageChange: value => dispatch(changeValue('coverImage', value)),
|
||||
onSubmit: routerHistory => dispatch(submit(routerHistory)),
|
||||
setUp: group => dispatch(setUp(group)),
|
||||
onTitleChange: value => dispatch(changeValue('title', value)),
|
||||
onDescriptionChange: value => dispatch(changeValue('description', value)),
|
||||
onCoverImageChange: value => dispatch(changeValue('coverImage', value)),
|
||||
onSubmit: routerHistory => dispatch(submit(routerHistory)),
|
||||
setUp: group => dispatch(setUp(group)),
|
||||
});
|
||||
|
||||
export default
|
||||
@@ -35,103 +35,103 @@ export default
|
||||
class Edit extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
router: PropTypes.object,
|
||||
router: PropTypes.object,
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
group: ImmutablePropTypes.map,
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
coverImage: PropTypes.object,
|
||||
disabled: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onTitleChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
group: ImmutablePropTypes.map,
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
coverImage: PropTypes.object,
|
||||
disabled: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onTitleChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
componentWillMount(nextProps) {
|
||||
if (this.props.group) {
|
||||
this.props.setUp(this.props.group);
|
||||
}
|
||||
if (this.props.group) {
|
||||
this.props.setUp(this.props.group);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (!this.props.group && nextProps.group) {
|
||||
this.props.setUp(nextProps.group);
|
||||
}
|
||||
if (!this.props.group && nextProps.group) {
|
||||
this.props.setUp(nextProps.group);
|
||||
}
|
||||
}
|
||||
|
||||
handleTitleChange = e => {
|
||||
this.props.onTitleChange(e.target.value);
|
||||
this.props.onTitleChange(e.target.value);
|
||||
}
|
||||
|
||||
handleDescriptionChange = e => {
|
||||
this.props.onDescriptionChange(e.target.value);
|
||||
this.props.onDescriptionChange(e.target.value);
|
||||
}
|
||||
|
||||
handleCoverImageChange = e => {
|
||||
this.props.onCoverImageChange(e.target.files[0]);
|
||||
this.props.onCoverImageChange(e.target.files[0]);
|
||||
}
|
||||
|
||||
handleSubmit = e => {
|
||||
e.preventDefault();
|
||||
this.props.onSubmit(this.context.router.history);
|
||||
e.preventDefault();
|
||||
this.props.onSubmit(this.context.router.history);
|
||||
}
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onSubmit(this.context.router.history);
|
||||
this.props.onSubmit(this.context.router.history);
|
||||
}
|
||||
|
||||
render () {
|
||||
const { group, title, description, coverImage, disabled, intl } = this.props;
|
||||
render() {
|
||||
const { group, title, description, coverImage, disabled, intl } = this.props;
|
||||
|
||||
if (typeof group === 'undefined') {
|
||||
return ( <ColumnIndicator type='loading' /> );
|
||||
} else if (group === false) {
|
||||
return (<ColumnIndicator type='missing' />);
|
||||
}
|
||||
if (typeof group === 'undefined') {
|
||||
return <ColumnIndicator type='loading' />
|
||||
} else if (group === false) {
|
||||
return <ColumnIndicator type='missing' />
|
||||
}
|
||||
|
||||
return (
|
||||
<form className='group-form' onSubmit={this.handleSubmit}>
|
||||
<div>
|
||||
<input
|
||||
className='standard'
|
||||
type='text'
|
||||
value={title}
|
||||
disabled={disabled}
|
||||
onChange={this.handleTitleChange}
|
||||
placeholder={intl.formatMessage(messages.title)}
|
||||
/>
|
||||
</div>
|
||||
return (
|
||||
<form className='group-form' onSubmit={this.handleSubmit}>
|
||||
<div>
|
||||
<input
|
||||
className='standard'
|
||||
type='text'
|
||||
value={title}
|
||||
disabled={disabled}
|
||||
onChange={this.handleTitleChange}
|
||||
placeholder={intl.formatMessage(messages.title)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<textarea
|
||||
className='standard'
|
||||
type='text'
|
||||
value={description}
|
||||
disabled={disabled}
|
||||
onChange={this.handleDescriptionChange}
|
||||
placeholder={intl.formatMessage(messages.description)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<textarea
|
||||
className='standard'
|
||||
type='text'
|
||||
value={description}
|
||||
disabled={disabled}
|
||||
onChange={this.handleDescriptionChange}
|
||||
placeholder={intl.formatMessage(messages.description)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label htmlFor='group_cover_image' className={classNames('group-form__file-label', { 'group-form__file-label--selected': coverImage !== null })}>
|
||||
{intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
|
||||
</label>
|
||||
<div>
|
||||
<label htmlFor='group_cover_image' className={classNames('group-form__file-label', { 'group-form__file-label--selected': coverImage !== null })}>
|
||||
{intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
|
||||
</label>
|
||||
|
||||
<input
|
||||
type='file'
|
||||
className='group-form__file'
|
||||
id='group_cover_image'
|
||||
disabled={disabled}
|
||||
onChange={this.handleCoverImageChange}
|
||||
/>
|
||||
<input
|
||||
type='file'
|
||||
className='group-form__file'
|
||||
id='group_cover_image'
|
||||
disabled={disabled}
|
||||
onChange={this.handleCoverImageChange}
|
||||
/>
|
||||
|
||||
<button>{intl.formatMessage(messages.update)}</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
<button>{intl.formatMessage(messages.update)}</button>
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { shortNumberFormat } from '../../../utils/numbers';
|
||||
|
||||
const messages = defineMessages({
|
||||
members: { id: 'groups.card.members', defaultMessage: 'Members' },
|
||||
view: { id: 'groups.card.view', defaultMessage: 'View' },
|
||||
join: { id: 'groups.card.join', defaultMessage: 'Join' },
|
||||
role_member: { id: 'groups.card.roles.member', defaultMessage: 'You\'re a member' },
|
||||
role_admin: { id: 'groups.card.roles.admin', defaultMessage: 'You\'re an admin' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state, { id }) => ({
|
||||
group: state.getIn(['groups', id]),
|
||||
relationships: state.getIn(['group_relationships', id]),
|
||||
});
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class GroupCard extends ImmutablePureComponent {
|
||||
static propTypes = {
|
||||
group: ImmutablePropTypes.map,
|
||||
relationships: ImmutablePropTypes.map,
|
||||
}
|
||||
|
||||
getRole() {
|
||||
const { intl, relationships } = this.props;
|
||||
|
||||
if (!relationships) return null;
|
||||
if (relationships.get('admin')) return intl.formatMessage(messages.role_admin);
|
||||
if (relationships.get('member')) return intl.formatMessage(messages.role_member);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, group } = this.props;
|
||||
const coverImageUrl = group.get('cover_image_url');
|
||||
const role = this.getRole();
|
||||
|
||||
return (
|
||||
<Link to={`/groups/${group.get('id')}`} className="group-card">
|
||||
<div className="group-card__header">{coverImageUrl && <img alt="" src={coverImageUrl} />}</div>
|
||||
<div className="group-card__content">
|
||||
<div className="group-card__title">{group.get('title')}</div>
|
||||
<div className="group-card__meta"><strong>{shortNumberFormat(group.get('member_count'))}</strong> {intl.formatMessage(messages.members)}{role && <span> · {role}</span>}</div>
|
||||
<div className="group-card__description">{group.get('description')}</div>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { Link } from 'react-router-dom';
|
||||
import classNames from 'classnames';
|
||||
import { fetchGroups } from '../../../actions/groups';
|
||||
import { openModal } from '../../../actions/modal';
|
||||
import { me } from '../../../initial_state';
|
||||
import GroupCard from './card';
|
||||
import GroupCreate from '../create';
|
||||
|
||||
const messages = defineMessages({
|
||||
heading: { id: 'column.groups', defaultMessage: 'Groups' },
|
||||
create: { id: 'groups.create', defaultMessage: 'Create group' },
|
||||
tab_featured: { id: 'groups.tab_featured', defaultMessage: 'Featured' },
|
||||
tab_member: { id: 'groups.tab_member', defaultMessage: 'Member' },
|
||||
tab_admin: { id: 'groups.tab_admin', defaultMessage: 'Manage' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state, { activeTab }) => ({
|
||||
groupIds: state.getIn(['group_lists', activeTab]),
|
||||
account: state.getIn(['accounts', me]),
|
||||
});
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class Groups extends ImmutablePureComponent {
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
activeTab: PropTypes.string.isRequired,
|
||||
showCreateForm: PropTypes.bool,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
groups: ImmutablePropTypes.map,
|
||||
groupIds: ImmutablePropTypes.list,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
this.props.dispatch(fetchGroups(this.props.activeTab));
|
||||
}
|
||||
|
||||
componentDidUpdate(oldProps) {
|
||||
if (this.props.activeTab && this.props.activeTab !== oldProps.activeTab) {
|
||||
this.props.dispatch(fetchGroups(this.props.activeTab));
|
||||
}
|
||||
}
|
||||
|
||||
handleOpenProUpgradeModal = () => {
|
||||
this.props.dispatch(openModal('PRO_UPGRADE'));
|
||||
}
|
||||
|
||||
renderHeader() {
|
||||
const { intl, activeTab, account, onOpenProUpgradeModal } = this.props;
|
||||
|
||||
const isPro = account.get('is_pro');
|
||||
|
||||
return (
|
||||
<div className="group-column-header">
|
||||
<div className="group-column-header__cta">
|
||||
{
|
||||
account && isPro &&
|
||||
<Link to="/groups/create" className="button standard-small">{intl.formatMessage(messages.create)}</Link>
|
||||
}
|
||||
{
|
||||
account && !isPro &&
|
||||
<button onClick={this.handleOpenProUpgradeModal} className="button standard-small">{intl.formatMessage(messages.create)}</button>
|
||||
}
|
||||
</div>
|
||||
<div className="group-column-header__title">{intl.formatMessage(messages.heading)}</div>
|
||||
|
||||
<div className="column-header__wrapper">
|
||||
<h1 className="column-header">
|
||||
<Link to='/groups' className={classNames('btn grouped', {'active': 'featured' === activeTab})}>
|
||||
{intl.formatMessage(messages.tab_featured)}
|
||||
</Link>
|
||||
|
||||
<Link to='/groups/browse/member' className={classNames('btn grouped', {'active': 'member' === activeTab})}>
|
||||
{intl.formatMessage(messages.tab_member)}
|
||||
</Link>
|
||||
|
||||
<Link to='/groups/browse/admin' className={classNames('btn grouped', {'active': 'admin' === activeTab})}>
|
||||
{intl.formatMessage(messages.tab_admin)}
|
||||
</Link>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render () {
|
||||
const { groupIds, showCreateForm } = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{!showCreateForm && this.renderHeader()}
|
||||
{showCreateForm && <GroupCreate /> }
|
||||
|
||||
<div className="group-card-list">
|
||||
{groupIds.map(id => <GroupCard key={id} id={id} />)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { debounce } from 'lodash';
|
||||
import {
|
||||
fetchMembers,
|
||||
expandMembers,
|
||||
updateRole,
|
||||
createRemovedAccount,
|
||||
} from '../../../actions/groups';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import AccountContainer from '../../../containers/account_container';
|
||||
import ScrollableList from '../../../components/scrollable_list';
|
||||
|
||||
const mapStateToProps = (state, { params: { id } }) => ({
|
||||
group: state.getIn(['groups', id]),
|
||||
relationships: state.getIn(['group_relationships', id]),
|
||||
accountIds: state.getIn(['user_lists', 'groups', id, 'items']),
|
||||
hasMore: !!state.getIn(['user_lists', 'groups', id, 'next']),
|
||||
});
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
class GroupMembers extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
hasMore: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
const { params: { id } } = this.props;
|
||||
|
||||
this.props.dispatch(fetchMembers(id));
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.params.id !== this.props.params.id) {
|
||||
this.props.dispatch(fetchMembers(nextProps.params.id));
|
||||
}
|
||||
}
|
||||
|
||||
handleLoadMore = debounce(() => {
|
||||
this.props.dispatch(expandMembers(this.props.params.id));
|
||||
}, 300, { leading: true });
|
||||
|
||||
render () {
|
||||
const { accountIds, hasMore, group, relationships, dispatch } = this.props;
|
||||
|
||||
if (!group || !accountIds || !relationships) {
|
||||
return <LoadingIndicator />
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollableList
|
||||
scrollKey='members'
|
||||
hasMore={hasMore}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={<FormattedMessage id='group.members.empty' defaultMessage='This group does not has any members.' />}
|
||||
>
|
||||
{accountIds.map(id => {
|
||||
let menu = [];
|
||||
|
||||
if (relationships.get('admin')) {
|
||||
menu = [
|
||||
{ text: 'Remove from group', action: () => dispatch(createRemovedAccount(group.get('id'), id)) },
|
||||
{ text: 'Make administrator', action: () => dispatch(updateRole(group.get('id'), id, 'admin')) },
|
||||
]
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="group-account-wrapper" key={id}>
|
||||
<AccountContainer id={id} withNote={false} actionIcon="none" onActionClick={() => true} />
|
||||
{menu.length > 0 && <DropdownMenuContainer items={menu} icon='ellipsis-h' size={18} direction='right' />}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</ScrollableList>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { Link } from 'react-router-dom'
|
||||
import classNames from 'classnames'
|
||||
import { connectGroupStream } from '../../../actions/streaming'
|
||||
import { expandGroupTimeline } from '../../../actions/timelines'
|
||||
import StatusListContainer from '../../../containers/status_list_container'
|
||||
import ColumnSettingsContainer from './containers/column_settings_container'
|
||||
import Icon from '../../../components/icon'
|
||||
import ColumnIndicator from '../../../components/column_indicator'
|
||||
|
||||
const messages = defineMessages({
|
||||
tabLatest: { id: 'group.timeline.tab_latest', defaultMessage: 'Latest' },
|
||||
show: { id: 'group.timeline.show_settings', defaultMessage: 'Show settings' },
|
||||
hide: { id: 'group.timeline.hide_settings', defaultMessage: 'Hide settings' },
|
||||
empty: { id: 'empty_column.group', defaultMessage: 'There is nothing in this group yet. When members of this group post new statuses, they will appear here.' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
group: state.getIn(['groups', props.params.id]),
|
||||
relationships: state.getIn(['group_relationships', props.params.id]),
|
||||
hasUnread: state.getIn(['timelines', `group:${props.params.id}`, 'unread']) > 0,
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class GroupTimeline extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
router: PropTypes.object,
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
columnId: PropTypes.string,
|
||||
hasUnread: PropTypes.bool,
|
||||
group: PropTypes.oneOfType([ImmutablePropTypes.map, PropTypes.bool]),
|
||||
relationships: ImmutablePropTypes.map,
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
state = {
|
||||
collapsed: true,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { dispatch } = this.props
|
||||
const { id } = this.props.params
|
||||
|
||||
dispatch(expandGroupTimeline(id))
|
||||
|
||||
this.disconnect = dispatch(connectGroupStream(id))
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (this.disconnect) {
|
||||
this.disconnect()
|
||||
this.disconnect = null
|
||||
}
|
||||
}
|
||||
|
||||
handleLoadMore = maxId => {
|
||||
const { id } = this.props.params
|
||||
this.props.dispatch(expandGroupTimeline(id, { maxId }))
|
||||
}
|
||||
|
||||
handleToggleClick = (e) => {
|
||||
e.stopPropagation()
|
||||
this.setState({ collapsed: !this.state.collapsed })
|
||||
}
|
||||
|
||||
render() {
|
||||
const { columnId, group, relationships, account, intl } = this.props
|
||||
const { collapsed } = this.state
|
||||
const { id } = this.props.params
|
||||
|
||||
if (typeof group === 'undefined' || !relationships) {
|
||||
return (<ColumnIndicator type='loading' />)
|
||||
} else if (group === false) {
|
||||
return (<ColumnIndicator type='missing' />)
|
||||
}
|
||||
|
||||
return (
|
||||
<StatusListContainer
|
||||
alwaysPrepend
|
||||
scrollKey={`group_timeline-${columnId}`}
|
||||
timelineId={`group:${id}`}
|
||||
onLoadMore={this.handleLoadMore}
|
||||
group={group}
|
||||
withGroupAdmin={relationships && relationships.get('admin')}
|
||||
emptyMessage={intl.formatMessage(messages.empty)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
export { default } from './groups_collection';
|
||||
export { default } from './groups_collection'
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default } from './hashtag_timeline';
|
||||
export { default } from './hashtag_timeline'
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default } from './column_settings';
|
||||
export { default } from './column_settings'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './introduction';
|
||||
export { default } from './introduction'
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default } from './list';
|
||||
export { default } from './list'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './list_adder';
|
||||
export { default } from './list_adder'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './edit_list_form';
|
||||
export { default } from './edit_list_form'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './list_editor_search';
|
||||
export { default } from './list_editor_search'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './list_editor';
|
||||
export { default } from './list_editor'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './list_timeline';
|
||||
export { default } from './list_timeline'
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default } from './new_list_form';
|
||||
export { default } from './new_list_form'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './lists_directory';
|
||||
export { default } from './lists_directory'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './mutes';
|
||||
export { default } from './mutes'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './column_settings';
|
||||
export { default } from './column_settings'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './notification';
|
||||
export { default } from './notification'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './notification_filter_bar';
|
||||
export { default } from './notification_filter_bar'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './notifications';
|
||||
export { default } from './notifications'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './reblogs';
|
||||
export { default } from './reblogs'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './header';
|
||||
export { default } from './header'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './search';
|
||||
export { default } from './search'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './compose';
|
||||
export { default } from './compose'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './hashtag_timeline';
|
||||
export { default } from './hashtag_timeline'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './public_timeline';
|
||||
export { default } from './public_timeline'
|
||||
@@ -167,7 +167,7 @@ export default class Card extends ImmutablePureComponent {
|
||||
{trim(card.get('description') || '', maxDescription)}
|
||||
</p>
|
||||
<span className={[_s.default, _s.marginTopAuto, _s.flexRow, _s.alignItemsCenter, _s.colorSecondary, _s.text, _s.displayFlex, _s.textOverflowEllipsis, _s.fontSize13PX].join(' ')}>
|
||||
<Icon id='link' width='12px' height='12px' className={[_s.fillcolorSecondary, _s.marginRight5PX].join(' ')} fixedWidth />
|
||||
<Icon id='link' width='10px' height='10px' className={[_s.fillcolorSecondary, _s.marginRight5PX].join(' ')} fixedWidth />
|
||||
{provider}
|
||||
</span>
|
||||
</div>
|
||||
@@ -177,7 +177,7 @@ export default class Card extends ImmutablePureComponent {
|
||||
let thumbnail = interactive ?
|
||||
<img src={cardImg} className={[_s.default, _s.objectFitCover, _s.positionAbsolute, _s.width100PC, _s.height100PC, _s.top0, _s.right0, _s.bottom0, _s.left0].join(' ')} />
|
||||
:
|
||||
<img src={cardImg} className={[_s.default, _s.objectFitCover, _s.width400PX, _s.height260PX].join(' ')} />
|
||||
<img src={cardImg} className={[_s.default, _s.objectFitCover, _s.width330PX, _s.height220PX].join(' ')} />
|
||||
|
||||
if (interactive) {
|
||||
if (embedded) {
|
||||
@@ -231,7 +231,7 @@ export default class Card extends ImmutablePureComponent {
|
||||
<div className={[_s.default, _s.width100PC, _s.paddingHorizontal10PX].join(' ')}>
|
||||
<a
|
||||
href={card.get('url')}
|
||||
className={[_s.default, _s.cursorPointer, _s.flexRow, _s.overflowHidden, _s.noUnderline, _s.width100PC, _s.borderColorSecondary2, _s.border1PX, _s.radiusSmall].join(' ')}
|
||||
className={[_s.default, _s.cursorPointer, _s.flexRow, _s.overflowHidden, _s.noUnderline, _s.width100PC, _s.backgroundSubtle_onHover, _s.borderColorSecondary2, _s.border1PX, _s.radiusSmall].join(' ')}
|
||||
rel='noopener'
|
||||
ref={this.setRef}
|
||||
>
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default } from './card';
|
||||
export { default } from './card'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './detailed_status';
|
||||
export { default } from './detailed_status'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './detailed_status_action_bar';
|
||||
export { default } from './detailed_status_action_bar'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './status';
|
||||
export { default } from './status'
|
||||
@@ -1 +1 @@
|
||||
export { default } from './ui';
|
||||
export { default } from './ui'
|
||||
@@ -22,7 +22,7 @@ import UploadArea from '../../components/upload_area'
|
||||
// import { WhoToFollowPanel } from '../../components/panel'
|
||||
// import LinkFooter from '../../components/link_footer'
|
||||
import ProfilePage from '../../pages/profile_page'
|
||||
// import GroupPage from '../../pages/group_page'
|
||||
import GroupPage from '../../pages/group_page'
|
||||
import GroupsPage from '../../pages/groups_page'
|
||||
import SearchPage from '../../pages/search_page'
|
||||
import ErrorPage from '../../pages/error_page'
|
||||
@@ -40,30 +40,29 @@ import {
|
||||
AccountTimeline,
|
||||
// AccountGallery,
|
||||
HomeTimeline,
|
||||
// Followers,
|
||||
// Following,
|
||||
Followers,
|
||||
Following,
|
||||
// Reblogs,
|
||||
// Favourites,
|
||||
// Favorites,
|
||||
// DirectTimeline,
|
||||
// HashtagTimeline,
|
||||
Notifications,
|
||||
// FollowRequests,
|
||||
GenericNotFound,
|
||||
// FavouritedStatuses,
|
||||
FavoritedStatuses,
|
||||
// Blocks,
|
||||
// DomainBlocks,
|
||||
// Mutes,
|
||||
// PinnedStatuses,
|
||||
Search,
|
||||
// Explore,
|
||||
GroupsCollection,
|
||||
// GroupTimeline,
|
||||
GroupTimeline,
|
||||
ListTimeline,
|
||||
ListsDirectory,
|
||||
// GroupMembers,
|
||||
// GroupRemovedAccounts,
|
||||
// GroupCreate,
|
||||
// GroupEdit,
|
||||
GroupMembers,
|
||||
GroupRemovedAccounts,
|
||||
GroupCreate,
|
||||
GroupEdit,
|
||||
} from './util/async-components'
|
||||
import { me, meUsername } from '../../initial_state'
|
||||
|
||||
@@ -90,7 +89,7 @@ const keyMap = {
|
||||
forceNew: 'option+n',
|
||||
focusColumn: ['1', '2', '3', '4', '5', '6', '7', '8', '9'],
|
||||
reply: 'r',
|
||||
favourite: 'f',
|
||||
Favorite: 'f',
|
||||
boost: 'b',
|
||||
mention: 'm',
|
||||
open: ['enter', 'o'],
|
||||
@@ -101,7 +100,7 @@ const keyMap = {
|
||||
goToHome: 'g h',
|
||||
goToNotifications: 'g n',
|
||||
goToStart: 'g s',
|
||||
goToFavourites: 'g f',
|
||||
goToFavorites: 'g f',
|
||||
goToPinned: 'g p',
|
||||
goToProfile: 'g u',
|
||||
goToBlocked: 'g b',
|
||||
@@ -154,15 +153,13 @@ class SwitchingArea extends PureComponent {
|
||||
<WrappedRoute path='/groups/browse/member' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'member' }} />
|
||||
<WrappedRoute path='/groups/browse/admin' exact page={GroupsPage} component={GroupsCollection} content={children} componentParams={{ activeTab: 'admin' }} />
|
||||
|
||||
{ /*
|
||||
<WrappedRoute path='/groups/create' page={GroupsPage} component={Groups} content={children} componentParams={{ showCreateForm: true, activeTab: 'featured' }} />
|
||||
<WrappedRoute path='/groups/create' page={GroupsPage} component={GroupCreate} content={children} componentParams={{ showCreateForm: true, activeTab: 'featured' }} />
|
||||
<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/edit' page={GroupPage} component={GroupEdit} content={children} />
|
||||
<WrappedRoute path='/groups/:id' page={GroupPage} component={GroupTimeline} content={children} />
|
||||
|
||||
<WrappedRoute path='/tags/:id' publicRoute component={HashtagTimeline} content={children} />
|
||||
*/ }
|
||||
{ /* <WrappedRoute path='/tags/:id' publicRoute component={HashtagTimeline} content={children} /> */}
|
||||
|
||||
<WrappedRoute path='/lists' exact page={ListsPage} component={ListsDirectory} content={children} />
|
||||
<WrappedRoute path='/list/:id' page={ListPage} component={ListTimeline} content={children} />
|
||||
@@ -189,28 +186,25 @@ class SwitchingArea extends PureComponent {
|
||||
<Redirect from='/@:username' to='/:username' exact />
|
||||
<WrappedRoute path='/:username' publicRoute exact page={ProfilePage} component={AccountTimeline} content={children} />
|
||||
|
||||
{ /*
|
||||
<Redirect from='/@:username/with_replies' to='/:username/with_replies' />
|
||||
<WrappedRoute path='/:username/with_replies' component={AccountTimeline} page={ProfilePage} content={children} componentParams={{ withReplies: true }} />
|
||||
<Redirect from='/@:username/comments' to='/:username/comments' />
|
||||
<WrappedRoute path='/:username/comments' page={ProfilePage} component={AccountTimeline} content={children} componentParams={{ commentsOnly: true }} />
|
||||
|
||||
<Redirect from='/@:username/followers' to='/:username/followers' />
|
||||
<WrappedRoute path='/:username/followers' component={Followers} page={ProfilePage} content={children} />
|
||||
<WrappedRoute path='/:username/followers' page={ProfilePage} component={Followers} content={children} />
|
||||
|
||||
<Redirect from='/@:username/following' to='/:username/following' />
|
||||
<WrappedRoute path='/:username/following' component={Following} page={ProfilePage} content={children} />
|
||||
|
||||
<WrappedRoute path='/:username/following' page={ProfilePage} component={Following} content={children} />
|
||||
{ /*
|
||||
<Redirect from='/@:username/media' to='/:username/media' />
|
||||
<WrappedRoute path='/:username/media' component={AccountGallery} page={ProfilePage} content={children} />
|
||||
|
||||
<Redirect from='/@:username/tagged/:tag' to='/:username/tagged/:tag' exact />
|
||||
<WrappedRoute path='/:username/tagged/:tag' exact component={AccountTimeline} page={ProfilePage} content={children} />
|
||||
|
||||
*/ }
|
||||
<Redirect from='/@:username/favorites' to='/:username/favorites' />
|
||||
<WrappedRoute path='/:username/favorites' component={FavouritedStatuses} page={ProfilePage} content={children} />
|
||||
|
||||
<Redirect from='/@:username/pins' to='/:username/pins' />
|
||||
<WrappedRoute path='/:username/pins' component={PinnedStatuses} page={ProfilePage} content={children} />
|
||||
<WrappedRoute path='/:username/favorites' page={ProfilePage} component={FavoritedStatuses} content={children} />
|
||||
|
||||
{ /*
|
||||
<Redirect from='/@:username/posts/:statusId' to='/:username/posts/:statusId' exact />
|
||||
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact component={Status} content={children} />
|
||||
*/ }
|
||||
@@ -473,7 +467,7 @@ class UI extends PureComponent {
|
||||
this.context.router.history.push('/getting-started')
|
||||
}
|
||||
|
||||
handleHotkeyGoToFavourites = () => {
|
||||
handleHotkeyGoToFavorites = () => {
|
||||
this.context.router.history.push(`/${meUsername}/favorites`)
|
||||
}
|
||||
|
||||
@@ -515,7 +509,7 @@ class UI extends PureComponent {
|
||||
goToHome: this.handleHotkeyGoToHome,
|
||||
goToNotifications: this.handleHotkeyGoToNotifications,
|
||||
goToStart: this.handleHotkeyGoToStart,
|
||||
goToFavourites: this.handleHotkeyGoToFavourites,
|
||||
goToFavorites: this.handleHotkeyGoToFavorites,
|
||||
goToPinned: this.handleHotkeyGoToPinned,
|
||||
goToProfile: this.handleHotkeyGoToProfile,
|
||||
goToBlocked: this.handleHotkeyGoToBlocked,
|
||||
|
||||
@@ -27,19 +27,19 @@ export function ListTimeline() {
|
||||
}
|
||||
|
||||
export function GroupTimeline() {
|
||||
return import(/* webpackChunkName: "features/groups/timeline" */'../../groups/timeline')
|
||||
return import(/* webpackChunkName: "features/group_timeline" */'../../group_timeline')
|
||||
}
|
||||
|
||||
export function GroupMembers() {
|
||||
return import(/* webpackChunkName: "features/groups/timeline" */'../../groups/members')
|
||||
return import(/* webpackChunkName: "features/group_members" */'../../group_members')
|
||||
}
|
||||
|
||||
export function GroupRemovedAccounts() {
|
||||
return import(/* webpackChunkName: "features/groups/timeline" */'../../groups/removed_accounts')
|
||||
return import(/* webpackChunkName: "features/group_removed_accounts" */'../../group_removed_accounts')
|
||||
}
|
||||
|
||||
export function GroupCreate() {
|
||||
return import(/* webpackChunkName: "features/groups/timeline" */'../../groups/create')
|
||||
return import(/* webpackChunkName: "features/groups_create" */'../../group_create')
|
||||
}
|
||||
|
||||
export function GroupEdit() {
|
||||
@@ -87,7 +87,7 @@ export function GenericNotFound() {
|
||||
}
|
||||
|
||||
export function FavoritedStatuses() {
|
||||
return import(/* webpackChunkName: "features/favourited_statuses" */'../../favourited_statuses')
|
||||
return import(/* webpackChunkName: "features/favorited_statuses" */'../../favorited_statuses')
|
||||
}
|
||||
|
||||
export function Blocks() {
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { default } from './video';
|
||||
export { default } from './video'
|
||||
Reference in New Issue
Block a user