Progress
This commit is contained in:
@@ -98,8 +98,12 @@ class AccountGallery extends ImmutablePureComponent {
|
||||
>
|
||||
|
||||
{
|
||||
attachments.map((attachment) => (
|
||||
<MediaItem key={attachment.get('id')} attachment={attachment} />
|
||||
attachments.map((attachment, i) => (
|
||||
<MediaItem
|
||||
key={attachment.get('id')}
|
||||
attachment={attachment}
|
||||
account={account}
|
||||
/>
|
||||
))
|
||||
}
|
||||
|
||||
@@ -108,16 +112,16 @@ class AccountGallery extends ImmutablePureComponent {
|
||||
<ColumnIndicator type='loading' />
|
||||
}
|
||||
|
||||
{ /*
|
||||
attachments.size === 0 &&
|
||||
<ColumnIndicator type='empty' message={intl.formatMessage(messages.none)} />
|
||||
*/ }
|
||||
|
||||
{
|
||||
hasMore && !(isLoading && attachments.size === 0) &&
|
||||
<LoadMore visible={!isLoading} onClick={this.handleLoadOlder} />
|
||||
!isLoading && attachments.size === 0 &&
|
||||
<ColumnIndicator type='error' message={intl.formatMessage(messages.none)} />
|
||||
}
|
||||
</div>
|
||||
|
||||
{
|
||||
hasMore && !(isLoading && attachments.size === 0) &&
|
||||
<LoadMore visible={!isLoading} onClick={this.handleLoadOlder} />
|
||||
}
|
||||
</Block>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import { fetchReposts } from '../actions/interactions';
|
||||
import { fetchStatus } from '../actions/statuses';
|
||||
import { makeGetStatus } from '../selectors';
|
||||
import Account from '../components/account';
|
||||
import ColumnIndicator from '../components/column_indicator';
|
||||
import ScrollableList from '../components/scrollable_list';
|
||||
|
||||
const mapStateToProps = (state, props) => {
|
||||
const getStatus = makeGetStatus();
|
||||
const status = getStatus(state, {
|
||||
id: props.params.statusId,
|
||||
username: props.params.username,
|
||||
});
|
||||
|
||||
return {
|
||||
status,
|
||||
accountIds: state.getIn(['user_lists', 'favorites', props.params.statusId]),
|
||||
};
|
||||
};
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
class Favorites extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
status: ImmutablePropTypes.map,
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
this.props.dispatch(fetchReposts(this.props.params.statusId));
|
||||
this.props.dispatch(fetchStatus(this.props.params.statusId));
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
|
||||
this.props.dispatch(fetchReposts(nextProps.params.statusId));
|
||||
this.props.dispatch(fetchStatus(nextProps.params.statusId));
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { accountIds, status } = this.props;
|
||||
|
||||
if (!accountIds) {
|
||||
return <ColumnIndicator type='loading' />
|
||||
} else if (!status) {
|
||||
return <ColumnIndicator type='missing' />
|
||||
}
|
||||
|
||||
return (
|
||||
<ScrollableList
|
||||
scrollKey='reposts'
|
||||
emptyMessage={<FormattedMessage id='status.reposts.empty' defaultMessage='No one has reposted this gab yet. When someone does, they will show up here.' />}
|
||||
>
|
||||
{
|
||||
accountIds.map(id =>
|
||||
<Account key={id} id={id} />
|
||||
)
|
||||
}
|
||||
</ScrollableList>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -41,7 +41,7 @@ class Following extends ImmutablePureComponent {
|
||||
hasMore: PropTypes.bool,
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
componentDidMount() {
|
||||
const { accountId } = this.props
|
||||
|
||||
if (!!accountId && accountId !== -1) {
|
||||
@@ -67,7 +67,7 @@ class Following extends ImmutablePureComponent {
|
||||
account,
|
||||
accountIds,
|
||||
hasMore,
|
||||
intl
|
||||
intl,
|
||||
} = this.props
|
||||
|
||||
if (!account) return null
|
||||
|
||||
@@ -2,12 +2,20 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import isObject from 'lodash.isobject'
|
||||
import { changeValue, submit, setUp, reset } from '../actions/group_editor'
|
||||
import ColumnIndicator from '../components/column_indicator';
|
||||
import {
|
||||
changeGroupTitle,
|
||||
changeGroupDescription,
|
||||
changeGroupCoverImage,
|
||||
submit,
|
||||
setGroup,
|
||||
resetEditor,
|
||||
} from '../actions/group_editor'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import Button from '../components/button'
|
||||
import Divider from '../components/divider'
|
||||
import Input from '../components/input'
|
||||
import Text from '../components/text'
|
||||
import Form from '../components/form'
|
||||
import Textarea from '../components/textarea'
|
||||
import FileInput from '../components/file_input'
|
||||
|
||||
@@ -18,6 +26,8 @@ const messages = defineMessages({
|
||||
coverImageChange: { id: 'groups.form.coverImageChange', defaultMessage: 'Banner image selected' },
|
||||
create: { id: 'groups.form.create', defaultMessage: 'Create group' },
|
||||
update: { id: 'groups.form.update', defaultMessage: 'Update group' },
|
||||
titlePlaceholder: { id: 'groups.form.title_placeholder', defaultMessage: 'New group title...' },
|
||||
descriptionPlaceholder: { id: 'groups.form.description_placeholder', defaultMessage: 'Some group description...' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state, { params }) => {
|
||||
@@ -27,26 +37,37 @@ const mapStateToProps = (state, { params }) => {
|
||||
return {
|
||||
group,
|
||||
error: groupId && !group,
|
||||
title: state.getIn(['group_editor', 'title']),
|
||||
description: state.getIn(['group_editor', 'description']),
|
||||
titleValue: state.getIn(['group_editor', 'title']),
|
||||
descriptionValue: state.getIn(['group_editor', 'description']),
|
||||
coverImage: state.getIn(['group_editor', 'coverImage']),
|
||||
disabled: state.getIn(['group_editor', 'isSubmitting']),
|
||||
isSubmitting: 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)),
|
||||
reset: () => dispatch(reset()),
|
||||
setUp: group => dispatch(setUp(group)),
|
||||
onTitleChange: (value) => {
|
||||
dispatch(changeGroupTitle(value))
|
||||
},
|
||||
onDescriptionChange: (value) => {
|
||||
dispatch(changeGroupDescription(value))
|
||||
},
|
||||
onCoverImageChange: (imageData) => {
|
||||
console.log("imageData:", imageData)
|
||||
dispatch(changeGroupCoverImage(imageData))
|
||||
},
|
||||
onResetEditor: () => {
|
||||
dispatch(resetEditor())
|
||||
},
|
||||
onSetGroup: (group) => {
|
||||
dispatch(setGroup(group))
|
||||
},
|
||||
onSubmit: (routerHistory) => dispatch(submit(routerHistory)),
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
@injectIntl
|
||||
class Create extends ImmutablePureComponent {
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
class GroupCreate extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
router: PropTypes.object
|
||||
@@ -54,43 +75,45 @@ class Create extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
group: ImmutablePropTypes.map,
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string.isRequired,
|
||||
titleValue: PropTypes.string.isRequired,
|
||||
descriptionValue: PropTypes.string.isRequired,
|
||||
coverImage: PropTypes.object,
|
||||
disabled: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onTitleChange: PropTypes.func.isRequired,
|
||||
onDescriptionChange: PropTypes.func.isRequired,
|
||||
onResetEditor: PropTypes.func.isRequired,
|
||||
onSetGroup: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
onCloseModal: PropTypes.func,
|
||||
isSubmitting: PropTypes.bool,
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
updateOnProps = [
|
||||
'group',
|
||||
'titleValue',
|
||||
'descriptionValue',
|
||||
'coverImage',
|
||||
'isSubmitting',
|
||||
]
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.props.group) {
|
||||
this.props.reset()
|
||||
this.props.onResetEditor()
|
||||
} else {
|
||||
this.props.setUp(this.props.group)
|
||||
this.props.onSetGroup(this.props.group)
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (this.props.group !== nextProps.group && !!nextProps.group) {
|
||||
this.props.setUp(nextProps.group)
|
||||
this.props.onSetGroup(nextProps.group)
|
||||
}
|
||||
}
|
||||
|
||||
handleTitleChange = e => {
|
||||
this.props.onTitleChange(e.target.value)
|
||||
}
|
||||
|
||||
handleDescriptionChange = e => {
|
||||
this.props.onDescriptionChange(e.target.value)
|
||||
}
|
||||
|
||||
handleCoverImageChange = e => {
|
||||
handleCoverImageChange = (e) => {
|
||||
this.props.onCoverImageChange(e.target.files[0])
|
||||
}
|
||||
|
||||
handleSubmit = e => {
|
||||
handleSubmit = (e) => {
|
||||
e.preventDefault()
|
||||
this.props.onSubmit(this.context.router.history)
|
||||
}
|
||||
@@ -99,11 +122,14 @@ class Create extends ImmutablePureComponent {
|
||||
const {
|
||||
group,
|
||||
error,
|
||||
title,
|
||||
description,
|
||||
titleValue,
|
||||
descriptionValue,
|
||||
coverImage,
|
||||
disabled,
|
||||
intl
|
||||
intl,
|
||||
onTitleChange,
|
||||
onDescriptionChange,
|
||||
isSubmitting,
|
||||
onSubmit,
|
||||
} = this.props
|
||||
|
||||
if (!group && error) {
|
||||
@@ -111,30 +137,30 @@ class Create extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
return (
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<Form onSubmit={onSubmit}>
|
||||
<Input
|
||||
title={intl.formatMessage(messages.title)}
|
||||
value={title}
|
||||
disabled={disabled}
|
||||
onChange={this.handleTitleChange}
|
||||
placeholder={'New group title...'}
|
||||
value={titleValue}
|
||||
onChange={onTitleChange}
|
||||
disabled={isSubmitting}
|
||||
placeholder={intl.formatMessage(messages.titlePlaceholder)}
|
||||
/>
|
||||
|
||||
<Divider isInvisible />
|
||||
|
||||
<Textarea
|
||||
title={intl.formatMessage(messages.description)}
|
||||
value={description}
|
||||
disabled={disabled}
|
||||
onChange={this.handleDescriptionChange}
|
||||
placeholder={'Some group description...'}
|
||||
value={descriptionValue}
|
||||
onChange={onDescriptionChange}
|
||||
placeholder={intl.formatMessage(messages.descriptionPlaceholder)}
|
||||
disabled={isSubmitting}
|
||||
/>
|
||||
|
||||
<Divider isInvisible />
|
||||
|
||||
<FileInput
|
||||
disabled={isSubmitting}
|
||||
title={intl.formatMessage(coverImage === null ? messages.coverImage : messages.coverImageChange)}
|
||||
disabled={disabled}
|
||||
onChange={this.handleCoverImageChange}
|
||||
width='340px'
|
||||
height='145px'
|
||||
@@ -142,13 +168,16 @@ class Create extends ImmutablePureComponent {
|
||||
|
||||
<Divider isInvisible />
|
||||
|
||||
<Button className={_s.ml10}>
|
||||
<Text color='white'>
|
||||
<Button
|
||||
isDisabled={!titleValue || !descriptionValue && !isSubmitting}
|
||||
onClick={this.handleSubmit}
|
||||
>
|
||||
<Text color='inherit' align='center'>
|
||||
{intl.formatMessage(!!group ? messages.update : messages.create)}
|
||||
</Text>
|
||||
</Button>
|
||||
|
||||
</form>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ class GroupTimeline extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
return (
|
||||
<StatusListContainer
|
||||
<StatusList
|
||||
alwaysPrepend
|
||||
scrollKey={`group_timeline-${columnId}`}
|
||||
timelineId={`group:${id}`}
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import { changeListEditorTitle, submitListEditor } from '../actions/lists'
|
||||
import { closeModal } from '../actions/modal'
|
||||
import { MODAL_LIST_CREATE } from '../constants'
|
||||
import Button from '../components/button'
|
||||
import Input from '../components/input'
|
||||
import Form from '../components/form'
|
||||
import Text from '../components/text'
|
||||
|
||||
const messages = defineMessages({
|
||||
label: { id: 'lists.new.title_placeholder', defaultMessage: 'New list title' },
|
||||
create: { id: 'lists.new.create_title', defaultMessage: 'Create' },
|
||||
create: { id: 'lists.new.create_title', defaultMessage: 'Create list' },
|
||||
list_description: { id: 'list.description', defaultMessage: 'Lists are private and only you can see who is on a list.\nNo one else can view your lists. No one knows that they are on your list.' },
|
||||
new_list_placeholder: { id: 'list.title_placeholder', defaultMessage: 'My new list...', },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => ({
|
||||
@@ -14,9 +19,12 @@ const mapStateToProps = (state) => ({
|
||||
disabled: state.getIn(['listEditor', 'isSubmitting']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onChange: value => dispatch(changeListEditorTitle(value)),
|
||||
onSubmit: () => dispatch(submitListEditor(true)),
|
||||
const mapDispatchToProps = (dispatch, { isModal }) => ({
|
||||
onChange: (value) => dispatch(changeListEditorTitle(value)),
|
||||
onSubmit: () => {
|
||||
if (isModal) dispatch(closeModal(MODAL_LIST_CREATE))
|
||||
dispatch(submitListEditor(true))
|
||||
},
|
||||
})
|
||||
|
||||
export default
|
||||
@@ -25,49 +33,47 @@ export default
|
||||
class ListCreate extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
value: PropTypes.string.isRequired,
|
||||
disabled: PropTypes.bool,
|
||||
value: PropTypes.string,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
isModal: PropTypes.bool,
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
value,
|
||||
disabled,
|
||||
intl,
|
||||
onSubmit,
|
||||
onChange
|
||||
onChange,
|
||||
} = this.props
|
||||
|
||||
const isDisabled = !value
|
||||
|
||||
return (
|
||||
<form onSubmit={onSubmit}>
|
||||
<Form>
|
||||
<Input
|
||||
title={intl.formatMessage(messages.label)}
|
||||
placeholder='My new list...'
|
||||
placeholder={intl.formatMessage(messages.new_list_placeholder)}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
onSubmit={onSubmit}
|
||||
disabled={disabled}
|
||||
/>
|
||||
|
||||
<div className={[_s.default, _s.my10, _s.py5, _s.ml10].join(' ')}>
|
||||
<Text color='secondary' size='small'>
|
||||
Lists are private and only you can see who is on a list.<br/>
|
||||
No one else can view your lists. No one knows that they are on your list.
|
||||
{intl.formatMessage(messages.list_description)}
|
||||
</Text>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
className={_s.ml10}
|
||||
type='submit'
|
||||
isDisabled={isDisabled}
|
||||
onClick={onSubmit}
|
||||
>
|
||||
<Text color='white'>
|
||||
<Text color='inherit' align='center'>
|
||||
{intl.formatMessage(messages.create)}
|
||||
</Text>
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ const mapStateToProps = (state) => ({
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onSubmit: value => dispatch(fetchListSuggestions(value)),
|
||||
onSubmit: (value) => dispatch(fetchListSuggestions(value)),
|
||||
onClear: () => dispatch(clearListSuggestions()),
|
||||
onChange: value => dispatch(changeListSuggestions(value)),
|
||||
onChange: (value) => dispatch(changeListSuggestions(value)),
|
||||
});
|
||||
|
||||
export default
|
||||
|
||||
@@ -7,6 +7,7 @@ import Account from './components/account'
|
||||
import ListEditorSearch from './components/list_editor_search'
|
||||
import EditListForm from './components/edit_list_form/edit_list_form'
|
||||
import Button from '../../components/button'
|
||||
import Form from '../../components/form'
|
||||
import Input from '../../components/input'
|
||||
|
||||
const mapStateToProps = (state, { params }) => {
|
||||
@@ -24,7 +25,7 @@ const mapStateToProps = (state, { params }) => {
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
onInitialize: listId => dispatch(setupListEditor(listId)),
|
||||
onInitialize: (listId) => dispatch(setupListEditor(listId)),
|
||||
onReset: () => dispatch(resetListEditor()),
|
||||
})
|
||||
|
||||
@@ -80,7 +81,7 @@ class ListEdit extends ImmutablePureComponent {
|
||||
console.log("title:", title)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Form>
|
||||
<Input
|
||||
title={intl.formatMessage(messages.editListTitle)}
|
||||
placeholder='My new list title...'
|
||||
@@ -90,8 +91,6 @@ class ListEdit extends ImmutablePureComponent {
|
||||
// disabled={disabled}
|
||||
/>
|
||||
|
||||
{
|
||||
/*
|
||||
<div className='compose-modal__header'>
|
||||
<h3 className='compose-modal__header__title'>
|
||||
{intl.formatMessage(messages.editList)}
|
||||
@@ -119,9 +118,8 @@ class ListEdit extends ImmutablePureComponent {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
*/ }
|
||||
|
||||
</div>
|
||||
</Form>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
||||
import { connectListStream } from '../actions/streaming';
|
||||
import { expandListTimeline } from '../actions/timelines';
|
||||
import { fetchList, deleteList } from '../actions/lists';
|
||||
import { openModal } from '../actions/modal';
|
||||
import StatusList from '../components/status_list';
|
||||
import ColumnIndicator from '../components/column_indicator';
|
||||
import Button from '../components/button';
|
||||
|
||||
const messages = defineMessages({
|
||||
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
|
||||
deleteConfirm: { id: 'confirmations.delete_list.confirm', defaultMessage: 'Delete' },
|
||||
});
|
||||
import { Fragment } from 'react'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { FormattedMessage } from 'react-intl'
|
||||
import { connectListStream } from '../actions/streaming'
|
||||
import { expandListTimeline } from '../actions/timelines'
|
||||
import { fetchList, deleteList } from '../actions/lists'
|
||||
import { openModal } from '../actions/modal'
|
||||
import StatusList from '../components/status_list'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import Button from '../components/button'
|
||||
import Text from '../components/text'
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
list: state.getIn(['lists', props.params.id]),
|
||||
});
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
@injectIntl
|
||||
class ListTimeline extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
@@ -35,84 +31,76 @@ class ListTimeline extends ImmutablePureComponent {
|
||||
PropTypes.bool,
|
||||
]),
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.handleConnect(this.props.params.id);
|
||||
this.handleConnect(this.props.params.id)
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.handleDisconnect();
|
||||
this.handleDisconnect()
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.params.id !== this.props.params.id) {
|
||||
this.handleDisconnect();
|
||||
this.handleConnect(nextProps.params.id);
|
||||
this.handleDisconnect()
|
||||
this.handleConnect(nextProps.params.id)
|
||||
}
|
||||
}
|
||||
|
||||
handleConnect(id) {
|
||||
const { dispatch } = this.props;
|
||||
const { dispatch } = this.props
|
||||
|
||||
dispatch(fetchList(id));
|
||||
dispatch(expandListTimeline(id));
|
||||
dispatch(fetchList(id))
|
||||
dispatch(expandListTimeline(id))
|
||||
|
||||
this.disconnect = dispatch(connectListStream(id));
|
||||
this.disconnect = dispatch(connectListStream(id))
|
||||
}
|
||||
|
||||
handleDisconnect() {
|
||||
if (this.disconnect) {
|
||||
this.disconnect();
|
||||
this.disconnect = null;
|
||||
this.disconnect()
|
||||
this.disconnect = null
|
||||
}
|
||||
}
|
||||
|
||||
handleLoadMore = maxId => {
|
||||
const { id } = this.props.params;
|
||||
this.props.dispatch(expandListTimeline(id, { maxId }));
|
||||
handleLoadMore = (maxId) => {
|
||||
const { id } = this.props.params
|
||||
this.props.dispatch(expandListTimeline(id, { maxId }))
|
||||
}
|
||||
|
||||
handleEditClick = () => {
|
||||
this.props.dispatch(openModal('LIST_EDITOR', { listId: this.props.params.id }));
|
||||
}
|
||||
|
||||
handleDeleteClick = () => {
|
||||
const { dispatch, intl } = this.props;
|
||||
const { id } = this.props.params;
|
||||
|
||||
dispatch(openModal('CONFIRM', {
|
||||
message: intl.formatMessage(messages.deleteMessage),
|
||||
confirm: intl.formatMessage(messages.deleteConfirm),
|
||||
onConfirm: () => {
|
||||
dispatch(deleteList(id));
|
||||
this.context.router.history.push('/lists');
|
||||
},
|
||||
}));
|
||||
this.props.dispatch(openModal('LIST_EDITOR', { listId: this.props.params.id }))
|
||||
}
|
||||
|
||||
render() {
|
||||
const { list } = this.props;
|
||||
const { id } = this.props.params;
|
||||
const title = list ? list.get('title') : id;
|
||||
const { list } = this.props
|
||||
const { id } = this.props.params
|
||||
const title = list ? list.get('title') : id
|
||||
|
||||
if (typeof list === 'undefined') {
|
||||
return (<ColumnIndicator type='loading' />);
|
||||
return <ColumnIndicator type='loading' />
|
||||
} else if (list === false) {
|
||||
return (<ColumnIndicator type='missing' />);
|
||||
return <ColumnIndicator type='missing' />
|
||||
}
|
||||
|
||||
const emptyMessage = (
|
||||
<div>
|
||||
<div className={[_s.default].join(' ')}>
|
||||
<FormattedMessage
|
||||
id='empty_column.list'
|
||||
defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.' />
|
||||
<br/><br/>
|
||||
<Button onClick={this.handleEditClick}>
|
||||
<FormattedMessage id='list.click_to_add' defaultMessage='Click here to add people' />
|
||||
defaultMessage='There is nothing in this list yet. When members of this list post new statuses, they will appear here.'
|
||||
/>
|
||||
|
||||
<Button
|
||||
onClick={this.handleEditClick}
|
||||
className={[_s.mt10]}
|
||||
>
|
||||
<Text color='inherit'>
|
||||
<FormattedMessage id='list.click_to_add' defaultMessage='Click here to add people' />
|
||||
</Text>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
|
||||
return (
|
||||
<StatusList
|
||||
@@ -121,7 +109,7 @@ class ListTimeline extends ImmutablePureComponent {
|
||||
onLoadMore={this.handleLoadMore}
|
||||
emptyMessage={emptyMessage}
|
||||
/>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ class Notifications extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
handleLoadGap = (maxId) => {
|
||||
// maxId={index > 0 ? notifications.getIn([index - 1, 'id']) : null}
|
||||
this.props.dispatch(expandNotifications({ maxId }))
|
||||
}
|
||||
|
||||
@@ -122,13 +123,7 @@ class Notifications extends ImmutablePureComponent {
|
||||
scrollableContent = this.scrollableContent
|
||||
} else if (notifications.size > 0 || hasMore) {
|
||||
scrollableContent = notifications.map((item, index) => item === null ? (
|
||||
<LoadMore
|
||||
gap
|
||||
key={'gap:' + notifications.getIn([index + 1, 'id'])}
|
||||
disabled={isLoading}
|
||||
maxId={index > 0 ? notifications.getIn([index - 1, 'id']) : null}
|
||||
onClick={this.handleLoadGap}
|
||||
/>
|
||||
<LoadMore disabled={isLoading} onClick={this.handleLoadGap} />
|
||||
) : (
|
||||
<NotificationContainer
|
||||
key={`notification-${index}`}
|
||||
|
||||
72
app/javascript/gabsocial/features/status_likes.js
Normal file
72
app/javascript/gabsocial/features/status_likes.js
Normal file
@@ -0,0 +1,72 @@
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ColumnIndicator from '../components/column_indicator'
|
||||
import { fetchLikes } from '../actions/interactions'
|
||||
import Account from '../components/account'
|
||||
import ScrollableList from '../components/scrollable_list'
|
||||
|
||||
const messages = defineMessages({
|
||||
refresh: { id: 'refresh', defaultMessage: 'Refresh' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state, props) => ({
|
||||
accountIds: state.getIn(['user_lists', 'favourited_by', props.params.statusId]),
|
||||
});
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
@connect(mapStateToProps)
|
||||
class StatusLikes extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
shouldUpdateScroll: PropTypes.func,
|
||||
accountIds: ImmutablePropTypes.list,
|
||||
multiColumn: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
if (!this.props.accountIds) {
|
||||
this.props.dispatch(fetchLikes(this.props.params.statusId));
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
|
||||
this.props.dispatch(fetchLikes(nextProps.params.statusId));
|
||||
}
|
||||
}
|
||||
|
||||
handleRefresh = () => {
|
||||
this.props.dispatch(fetchLikes(this.props.params.statusId));
|
||||
}
|
||||
|
||||
render () {
|
||||
const { intl, shouldUpdateScroll, accountIds, multiColumn } = this.props;
|
||||
|
||||
if (!accountIds) {
|
||||
return <ColumnIndicator type='loading' />
|
||||
}
|
||||
|
||||
const emptyMessage = <FormattedMessage id='empty_column.favourites' defaultMessage='No one has favourited this toot yet. When someone does, they will show up here.' />;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ScrollableList
|
||||
scrollKey='favourites'
|
||||
shouldUpdateScroll={shouldUpdateScroll}
|
||||
emptyMessage={emptyMessage}
|
||||
bindToDocument={!multiColumn}
|
||||
>
|
||||
{accountIds.map(id =>
|
||||
<Account key={id} id={id} withNote={false} />,
|
||||
)}
|
||||
</ScrollableList>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,7 +23,7 @@ const mapStateToProps = (state, props) => {
|
||||
|
||||
export default
|
||||
@connect(mapStateToProps)
|
||||
class Reposts extends ImmutablePureComponent {
|
||||
class StatusReposts extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
@@ -6,6 +6,7 @@ import { Switch, Redirect, withRouter } from 'react-router-dom'
|
||||
import debounce from 'lodash.debounce'
|
||||
import { uploadCompose, resetCompose } from '../../actions/compose'
|
||||
import { expandHomeTimeline } from '../../actions/timelines'
|
||||
import { fetchGroups } from '../../actions/groups'
|
||||
import {
|
||||
initializeNotifications,
|
||||
expandNotifications,
|
||||
@@ -40,7 +41,6 @@ import {
|
||||
BlockedAccounts,
|
||||
BlockedDomains,
|
||||
CommunityTimeline,
|
||||
// Favorites,
|
||||
// Filters,
|
||||
Followers,
|
||||
Following,
|
||||
@@ -61,17 +61,17 @@ import {
|
||||
ListTimeline,
|
||||
Mutes,
|
||||
Notifications,
|
||||
Reposts,
|
||||
Search,
|
||||
// Shortcuts,
|
||||
Status,
|
||||
StatusLikes,
|
||||
StatusReposts,
|
||||
} from './util/async_components'
|
||||
import { me, meUsername } from '../../initial_state'
|
||||
|
||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
|
||||
// Without this it ends up in ~8 very commonly used bundles.
|
||||
import '../../components/status'
|
||||
import { fetchGroups } from '../../actions/groups'
|
||||
|
||||
const messages = defineMessages({
|
||||
beforeUnload: { id: 'ui.beforeunload', defaultMessage: 'Your draft will be lost if you leave Gab Social.' },
|
||||
@@ -116,7 +116,7 @@ class SwitchingArea extends PureComponent {
|
||||
onLayoutChange: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
componentDidMount() {
|
||||
window.addEventListener('resize', this.handleResize, {
|
||||
passive: true
|
||||
})
|
||||
@@ -209,10 +209,10 @@ class SwitchingArea extends PureComponent {
|
||||
<WrappedRoute path='/:username/posts/:statusId' publicRoute exact page={BasicPage} component={Status} content={children} componentParams={{ title: 'Status' }} />
|
||||
|
||||
<Redirect from='/@:username/posts/:statusId/reposts' to='/:username/posts/:statusId/reposts' />
|
||||
<WrappedRoute path='/:username/posts/:statusId/reposts' page={BasicPage} component={Reposts} content={children} componentParams={{ title: 'Reposts' }} />
|
||||
<WrappedRoute path='/:username/posts/:statusId/reposts' page={BasicPage} component={StatusReposts} content={children} componentParams={{ title: 'Reposts' }} />
|
||||
|
||||
{ /* <Redirect from='/@:username/posts/:statusId/favorites' to='/:username/posts/:statusId/favorites' />
|
||||
<WrappedRoute path='/:username/posts/:statusId/favorites' page={BasicPage} component={Favorites} content={children} componentParams={{ title: 'Favorites' }} /> */ }
|
||||
<Redirect from='/@:username/posts/:statusId/likes' to='/:username/posts/:statusId/likes' />
|
||||
<WrappedRoute path='/:username/posts/:statusId/likes' page={BasicPage} component={StatusLikes} content={children} componentParams={{ title: 'Likes' }} />
|
||||
|
||||
<WrappedRoute page={ErrorPage} component={GenericNotFound} content={children} />
|
||||
</Switch>
|
||||
@@ -349,7 +349,13 @@ class UI extends PureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillMount() {
|
||||
// componentWillMount() {
|
||||
|
||||
// }
|
||||
|
||||
componentDidMount() {
|
||||
// if (!me) return
|
||||
|
||||
window.addEventListener('beforeunload', this.handleBeforeUnload, false)
|
||||
|
||||
document.addEventListener('dragenter', this.handleDragEnter, false)
|
||||
@@ -370,15 +376,9 @@ class UI extends PureComponent {
|
||||
this.props.dispatch(expandHomeTimeline())
|
||||
this.props.dispatch(expandNotifications())
|
||||
this.props.dispatch(initializeNotifications())
|
||||
this.props.dispatch(fetchGroups('member'))
|
||||
|
||||
setTimeout(() => this.props.dispatch(fetchFilters()), 500)
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!me) return
|
||||
|
||||
// this.hotkeys.__mousetrap__.stopCallback = (e, element) => {
|
||||
// return ['TEXTAREA', 'SELECT', 'INPUT'].includes(element.tagName)
|
||||
// }
|
||||
@@ -435,7 +435,7 @@ class UI extends PureComponent {
|
||||
}
|
||||
|
||||
handleHotkeyToggleHelp = () => {
|
||||
this.props.dispatch(openModal("HOTKEYS"))
|
||||
this.props.dispatch(openModal('HOTKEYS'))
|
||||
}
|
||||
|
||||
handleHotkeyGoToHome = () => {
|
||||
@@ -471,7 +471,7 @@ class UI extends PureComponent {
|
||||
}
|
||||
|
||||
handleOpenComposeModal = () => {
|
||||
this.props.dispatch(openModal("COMPOSE"))
|
||||
this.props.dispatch(openModal('COMPOSE'))
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -1,34 +1,74 @@
|
||||
export function AccountTimeline() { return import(/* webpackChunkName: "features/account_timeline" */'../../account_timeline') }
|
||||
export function AccountGallery() { return import(/* webpackChunkName: "features/account_gallery" */'../../account_gallery') }
|
||||
export function ActionsModal() { return import(/* webpackChunkName: "components/actions_modal" */'../../../components/modal/actions_modal') }
|
||||
export function BlockAccountModal() { return import(/* webpackChunkName: "components/block_account_modal" */'../../../components/modal/block_account_modal') }
|
||||
export function BlockDomainModal() { return import(/* webpackChunkName: "components/block_domain_modal" */'../../../components/modal/block_domain_modal') }
|
||||
export function BlockedAccounts() { return import(/* webpackChunkName: "features/blocked_accounts" */'../../blocked_accounts') }
|
||||
export function BlockedDomains() { return import(/* webpackChunkName: "features/blocked_domains" */'../../blocked_domains') }
|
||||
export function BoostModal() { return import(/* webpackChunkName: "components/boost_modal" */'../../../components/modal/boost_modal') }
|
||||
export function CommunityTimeline() { return import(/* webpackChunkName: "features/community_timeline" */'../../community_timeline') }
|
||||
export function CommunityTimelineSettingsModal() { return import(/* webpackChunkName: "components/community_timeline_settings_modal" */'../../../components/modal/community_timeline_settings_modal') }
|
||||
export function Compose() { return import(/* webpackChunkName: "features/compose" */'../../compose') }
|
||||
export function ComposeForm() { return import(/* webpackChunkName: "components/compose_form" */'../../compose/components/compose_form') }
|
||||
export function ComposeModal() { return import(/* webpackChunkName: "components/compose_modal" */'../../../components/modal/compose_modal') }
|
||||
export function ConfirmationModal() { return import(/* webpackChunkName: "components/confirmation_modal" */'../../../components/modal/confirmation_modal') }
|
||||
export function ContentWarningPopover() { return import(/* webpackChunkName: "components/content_warning_popover" */'../../../components/popover/content_warning_popover') }
|
||||
export function DatePickerPopover() { return import(/* webpackChunkName: "components/date_picker_popover" */'../../../components/popover/date_picker_popover') }
|
||||
export function DisplayOptionsModal() { return import(/* webpackChunkName: "components/display_options_modal" */'../../../components/modal/display_options_modal') }
|
||||
export function EditProfileModal() { return import(/* webpackChunkName: "components/edit_profile_modal" */'../../../components/modal/edit_profile_modal') }
|
||||
export function EmbedModal() { return import(/* webpackChunkName: "modals/embed_modal" */'../../../components/modal/embed_modal') }
|
||||
export function EmojiPicker() { return import(/* webpackChunkName: "emoji_picker" */'../../../components/emoji/emoji_picker') }
|
||||
export function EmojiPickerPopover() { return import(/* webpackChunkName: "components/emoji_picker_popover" */'../../../components/popover/emoji_picker_popover') }
|
||||
export function Followers() { return import(/* webpackChunkName: "features/followers" */'../../followers') }
|
||||
export function Following() { return import(/* webpackChunkName: "features/following" */'../../following') }
|
||||
export function FollowRequests() { return import(/* webpackChunkName: "features/follow_requests" */'../../follow_requests') }
|
||||
export function LikedStatuses() { return import(/* webpackChunkName: "features/liked_statuses" */'../../liked_statuses') }
|
||||
export function GenericNotFound() { return import(/* webpackChunkName: "features/generic_not_found" */'../../generic_not_found') }
|
||||
export function GifPickerModal() { return import(/* webpackChunkName: "components/gif_picker_modal" */'../../../components/modal/gif_picker_modal') }
|
||||
export function GroupsCollection() { return import(/* webpackChunkName: "features/groups_collection" */'../../groups_collection') }
|
||||
export function GroupCreate() { return import(/* webpackChunkName: "features/group_create" */'../../group_create') }
|
||||
export function GroupCreateModal() { return import(/* webpackChunkName: "components/group_create_modal" */'../../../components/modal/group_create_modal') }
|
||||
export function GroupDeleteModal() { return import(/* webpackChunkName: "components/group_delete_modal" */'../../../components/modal/group_delete_modal') }
|
||||
export function GroupEditorModal() { return import(/* webpackChunkName: "components/group_editor_modal" */'../../../components/modal/group_editor_modal') }
|
||||
export function GroupInfoPopover() { return import(/* webpackChunkName: "components/group_info_popover" */'../../../components/popover/group_info_popover') }
|
||||
export function GroupMembers() { return import(/* webpackChunkName: "features/group_members" */'../../group_members') }
|
||||
export function GroupRemovedAccounts() { return import(/* webpackChunkName: "features/group_removed_accounts" */'../../group_removed_accounts') }
|
||||
export function GroupTimeline() { return import(/* webpackChunkName: "features/group_timeline" */'../../group_timeline') }
|
||||
export function HashtagTimeline() { return import(/* webpackChunkName: "features/hashtag_timeline" */'../../hashtag_timeline') }
|
||||
export function HashtagTimelineSettingsModal() { return import(/* webpackChunkName: "components/hashtag_timeline_settings_modal" */'../../../components/modal/hashtag_timeline_settings_modal') }
|
||||
export function HomeTimeline() { return import(/* webpackChunkName: "features/home_timeline" */'../../home_timeline') }
|
||||
export function HomeTimelineSettingsModal() { return import(/* webpackChunkName: "components/home_timeline_settings_modal" */'../../../components/modal/home_timeline_settings_modal') }
|
||||
export function HotkeysModal() { return import(/* webpackChunkName: "components/hotkeys_modal" */'../../../components/modal/hotkeys_modal') }
|
||||
export function ListCreate() { return import(/* webpackChunkName: "features/list_create" */'../../list_create') }
|
||||
export function ListCreateModal() { return import(/* webpackChunkName: "components/list_create_modal" */'../../../components/modal/list_create_modal') }
|
||||
export function ListDeleteModal() { return import(/* webpackChunkName: "components/list_delete_modal" */'../../../components/modal/list_delete_modal') }
|
||||
export function ListsDirectory() { return import(/* webpackChunkName: "features/lists_directory" */'../../lists_directory') }
|
||||
export function ListEdit() { return import(/* webpackChunkName: "features/list_editor" */'../../list_edit') }
|
||||
export function ListEditorModal() { return import(/* webpackChunkName: "components/list_editor_modal" */'../../../components/modal/list_editor_modal') }
|
||||
export function ListTimeline() { return import(/* webpackChunkName: "features/list_timeline" */'../../list_timeline') }
|
||||
export function ListTimelineSettingsModal() { return import(/* webpackChunkName: "components/list_timeline_settings_modal" */'../../../components/modal/list_timeline_settings_modal') }
|
||||
export function MediaGallery() { return import(/* webpackChunkName: "components/media_gallery" */'../../../components/media_gallery') }
|
||||
export function MediaModal() { return import(/* webpackChunkName: "components/media_modal" */'../../../components/modal/media_modal') }
|
||||
export function ModalLoading() { return import(/* webpackChunkName: "components/modal_loading" */'../../../components/modal/modal_loading') }
|
||||
export function Mutes() { return import(/* webpackChunkName: "features/mutes" */'../../mutes') }
|
||||
export function MuteModal() { return import(/* webpackChunkName: "modals/mute_modal" */'../../../components/modal/mute_modal') }
|
||||
export function Notifications() { return import(/* webpackChunkName: "features/notifications" */'../../notifications') }
|
||||
export function Reposts() { return import(/* webpackChunkName: "features/reposts" */'../../reposts') }
|
||||
export function ProfileOptionsPopover() { return import(/* webpackChunkName: "components/profile_options_popover" */'../../../components/popover/profile_options_popover') }
|
||||
export function ProUpgradeModal() { return import(/* webpackChunkName: "components/pro_upgrade_modal" */'../../../components/modal/pro_upgrade_modal') }
|
||||
export function ReportModal() { return import(/* webpackChunkName: "modals/report_modal" */'../../../components/modal/report_modal') }
|
||||
export function RepostOptionsPopover() { return import(/* webpackChunkName: "components/repost_options_popover" */'../../../components/popover/repost_options_popover') }
|
||||
export function Search() { return import(/*webpackChunkName: "features/search" */'../../search') }
|
||||
export function Status() { return import(/* webpackChunkName: "components/status" */'../../../components/status') }
|
||||
export function SearchPopover() { return import(/* webpackChunkName: "components/search_popover" */'../../../components/popover/search_popover') }
|
||||
export function SidebarMorePopover() { return import(/* webpackChunkName: "components/sidebar_more_popover" */'../../../components/popover/sidebar_more_popover') }
|
||||
export function StatusLikes() { return import(/* webpackChunkName: "features/status_likes" */'../../status_likes') }
|
||||
export function StatusOptionsPopover() { return import(/* webpackChunkName: "components/status_options_popover" */'../../../components/popover/status_options_popover') }
|
||||
export function StatusReposts() { return import(/* webpackChunkName: "features/status_reposts" */'../../status_reposts') }
|
||||
export function StatusRevisionsModal() { return import(/* webpackChunkName: "modals/status_revisions_modal" */'../../../components/modal/status_revisions_modal') }
|
||||
export function StatusSharePopover() { return import(/* webpackChunkName: "components/status_share_popover" */'../../../components/popover/status_share_popover') }
|
||||
export function StatusVisibilityPopover() { return import(/* webpackChunkName: "components/status_visibility_popover" */'../../../components/popover/status_visibility_popover') }
|
||||
export function UnauthorizedModal() { return import(/* webpackChunkName: "components/unauthorized_modal" */'../../../components/modal/unauthorized_modal') }
|
||||
export function UnfollowModal() { return import(/* webpackChunkName: "components/unfollow_modal" */'../../../components/modal/unfollow_modal') }
|
||||
export function UserInfoPopover() { return import(/* webpackChunkName: "components/user_info_popover" */'../../../components/popover/user_info_popover') }
|
||||
export function Video() { return import(/* webpackChunkName: "components/video" */'../../../components/video') }
|
||||
export function VideoModal() { return import(/* webpackChunkName: "components/video_modal" */'../../../components/modal/video_modal') }
|
||||
@@ -1,7 +1,7 @@
|
||||
import {
|
||||
fetchBundleRequest,
|
||||
fetchBundleSuccess,
|
||||
fetchBundleFail
|
||||
fetchBundleFail,
|
||||
} from '../../../actions/bundles'
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import api from '../../../api'
|
||||
import { Route } from 'react-router-dom'
|
||||
import BundleColumnError from '../../../components/bundle_column_error'
|
||||
import Bundle from './bundle'
|
||||
@@ -51,6 +52,15 @@ export default class WrappedRoute extends PureComponent {
|
||||
...rest
|
||||
} = this.props
|
||||
|
||||
// : todo :
|
||||
// api().get('/api/v1/accounts/verify_credentials')
|
||||
// .then((res) => {
|
||||
// console.log("res:", res)
|
||||
// })
|
||||
// .catch((err) => {
|
||||
// console.log("err:", err)
|
||||
// })
|
||||
|
||||
if (!publicRoute && !me) {
|
||||
const actualUrl = encodeURIComponent(this.props.computedMatch.url)
|
||||
return <Route path={this.props.path} component={() => {
|
||||
|
||||
Reference in New Issue
Block a user