[Glitch] Add editing for published statuses
Port 63002cde03
to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
parent
abd113167b
commit
5e67858fbc
|
@ -75,6 +75,8 @@ export const INIT_MEDIA_EDIT_MODAL = 'INIT_MEDIA_EDIT_MODAL';
|
||||||
export const COMPOSE_CHANGE_MEDIA_DESCRIPTION = 'COMPOSE_CHANGE_MEDIA_DESCRIPTION';
|
export const COMPOSE_CHANGE_MEDIA_DESCRIPTION = 'COMPOSE_CHANGE_MEDIA_DESCRIPTION';
|
||||||
export const COMPOSE_CHANGE_MEDIA_FOCUS = 'COMPOSE_CHANGE_MEDIA_FOCUS';
|
export const COMPOSE_CHANGE_MEDIA_FOCUS = 'COMPOSE_CHANGE_MEDIA_FOCUS';
|
||||||
|
|
||||||
|
export const COMPOSE_SET_STATUS = 'COMPOSE_SET_STATUS';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' },
|
uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' },
|
||||||
uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
|
uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
|
||||||
|
@ -88,6 +90,15 @@ export const ensureComposeIsVisible = (getState, routerHistory) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function setComposeToStatus(status, text, spoiler_text) {
|
||||||
|
return{
|
||||||
|
type: COMPOSE_SET_STATUS,
|
||||||
|
status,
|
||||||
|
text,
|
||||||
|
spoiler_text,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export function changeCompose(text) {
|
export function changeCompose(text) {
|
||||||
return {
|
return {
|
||||||
type: COMPOSE_CHANGE,
|
type: COMPOSE_CHANGE,
|
||||||
|
@ -150,8 +161,9 @@ export function directCompose(account, routerHistory) {
|
||||||
|
|
||||||
export function submitCompose(routerHistory) {
|
export function submitCompose(routerHistory) {
|
||||||
return function (dispatch, getState) {
|
return function (dispatch, getState) {
|
||||||
let status = getState().getIn(['compose', 'text'], '');
|
let status = getState().getIn(['compose', 'text'], '');
|
||||||
let media = getState().getIn(['compose', 'media_attachments']);
|
const media = getState().getIn(['compose', 'media_attachments']);
|
||||||
|
const statusId = getState().getIn(['compose', 'id'], null);
|
||||||
const spoilers = getState().getIn(['compose', 'spoiler']) || getState().getIn(['local_settings', 'always_show_spoilers_field']);
|
const spoilers = getState().getIn(['compose', 'spoiler']) || getState().getIn(['local_settings', 'always_show_spoilers_field']);
|
||||||
let spoilerText = spoilers ? getState().getIn(['compose', 'spoiler_text'], '') : '';
|
let spoilerText = spoilers ? getState().getIn(['compose', 'spoiler_text'], '') : '';
|
||||||
|
|
||||||
|
@ -159,20 +171,25 @@ export function submitCompose(routerHistory) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(submitComposeRequest());
|
|
||||||
if (getState().getIn(['compose', 'advanced_options', 'do_not_federate'])) {
|
if (getState().getIn(['compose', 'advanced_options', 'do_not_federate'])) {
|
||||||
status = status + ' 👁️';
|
status = status + ' 👁️';
|
||||||
}
|
}
|
||||||
api(getState).post('/api/v1/statuses', {
|
|
||||||
status,
|
dispatch(submitComposeRequest());
|
||||||
content_type: getState().getIn(['compose', 'content_type']),
|
|
||||||
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
api(getState).request({
|
||||||
media_ids: media.map(item => item.get('id')),
|
url: statusId === null ? '/api/v1/statuses' : `/api/v1/statuses/${statusId}`,
|
||||||
sensitive: getState().getIn(['compose', 'sensitive']) || (spoilerText.length > 0 && media.size !== 0),
|
method: statusId === null ? 'post' : 'put',
|
||||||
spoiler_text: spoilerText,
|
data: {
|
||||||
visibility: getState().getIn(['compose', 'privacy']),
|
status,
|
||||||
poll: getState().getIn(['compose', 'poll'], null),
|
content_type: getState().getIn(['compose', 'content_type']),
|
||||||
}, {
|
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
||||||
|
media_ids: media.map(item => item.get('id')),
|
||||||
|
sensitive: getState().getIn(['compose', 'sensitive']) || (spoilerText.length > 0 && media.size !== 0),
|
||||||
|
spoiler_text: spoilerText,
|
||||||
|
visibility: getState().getIn(['compose', 'privacy']),
|
||||||
|
poll: getState().getIn(['compose', 'poll'], null),
|
||||||
|
},
|
||||||
headers: {
|
headers: {
|
||||||
'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
|
'Idempotency-Key': getState().getIn(['compose', 'idempotencyKey']),
|
||||||
},
|
},
|
||||||
|
@ -202,14 +219,16 @@ export function submitCompose(routerHistory) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
insertIfOnline('home');
|
if (statusId === null) {
|
||||||
|
insertIfOnline('home');
|
||||||
|
}
|
||||||
|
|
||||||
if (response.data.in_reply_to_id === null && response.data.visibility === 'public') {
|
if (statusId === null && response.data.in_reply_to_id === null && response.data.visibility === 'public') {
|
||||||
insertIfOnline('community');
|
insertIfOnline('community');
|
||||||
if (!response.data.local_only) {
|
if (!response.data.local_only) {
|
||||||
insertIfOnline('public');
|
insertIfOnline('public');
|
||||||
}
|
}
|
||||||
} else if (response.data.visibility === 'direct') {
|
} else if (statusId === null && response.data.visibility === 'direct') {
|
||||||
insertIfOnline('direct');
|
insertIfOnline('direct');
|
||||||
}
|
}
|
||||||
}).catch(function (error) {
|
}).catch(function (error) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import api from 'flavours/glitch/util/api';
|
||||||
|
|
||||||
import { deleteFromTimelines } from './timelines';
|
import { deleteFromTimelines } from './timelines';
|
||||||
import { importFetchedStatus, importFetchedStatuses } from './importer';
|
import { importFetchedStatus, importFetchedStatuses } from './importer';
|
||||||
import { ensureComposeIsVisible } from './compose';
|
import { ensureComposeIsVisible, setComposeToStatus } from './compose';
|
||||||
|
|
||||||
export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST';
|
export const STATUS_FETCH_REQUEST = 'STATUS_FETCH_REQUEST';
|
||||||
export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS';
|
export const STATUS_FETCH_SUCCESS = 'STATUS_FETCH_SUCCESS';
|
||||||
|
@ -26,6 +26,10 @@ export const STATUS_UNMUTE_FAIL = 'STATUS_UNMUTE_FAIL';
|
||||||
|
|
||||||
export const REDRAFT = 'REDRAFT';
|
export const REDRAFT = 'REDRAFT';
|
||||||
|
|
||||||
|
export const STATUS_FETCH_SOURCE_REQUEST = 'STATUS_FETCH_SOURCE_REQUEST';
|
||||||
|
export const STATUS_FETCH_SOURCE_SUCCESS = 'STATUS_FETCH_SOURCE_SUCCESS';
|
||||||
|
export const STATUS_FETCH_SOURCE_FAIL = 'STATUS_FETCH_SOURCE_FAIL';
|
||||||
|
|
||||||
export function fetchStatusRequest(id, skipLoading) {
|
export function fetchStatusRequest(id, skipLoading) {
|
||||||
return {
|
return {
|
||||||
type: STATUS_FETCH_REQUEST,
|
type: STATUS_FETCH_REQUEST,
|
||||||
|
@ -81,6 +85,37 @@ export function redraft(status, raw_text, content_type) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const editStatus = (id, routerHistory) => (dispatch, getState) => {
|
||||||
|
let status = getState().getIn(['statuses', id]);
|
||||||
|
|
||||||
|
if (status.get('poll')) {
|
||||||
|
status = status.set('poll', getState().getIn(['polls', status.get('poll')]));
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(fetchStatusSourceRequest());
|
||||||
|
|
||||||
|
api(getState).get(`/api/v1/statuses/${id}/source`).then(response => {
|
||||||
|
dispatch(fetchStatusSourceSuccess());
|
||||||
|
ensureComposeIsVisible(getState, routerHistory);
|
||||||
|
dispatch(setComposeToStatus(status, response.data.text, response.data.spoiler_text));
|
||||||
|
}).catch(error => {
|
||||||
|
dispatch(fetchStatusSourceFail(error));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchStatusSourceRequest = () => ({
|
||||||
|
type: STATUS_FETCH_SOURCE_REQUEST,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const fetchStatusSourceSuccess = () => ({
|
||||||
|
type: STATUS_FETCH_SOURCE_SUCCESS,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const fetchStatusSourceFail = error => ({
|
||||||
|
type: STATUS_FETCH_SOURCE_FAIL,
|
||||||
|
error,
|
||||||
|
});
|
||||||
|
|
||||||
export function deleteStatus(id, routerHistory, withRedraft = false) {
|
export function deleteStatus(id, routerHistory, withRedraft = false) {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
let status = getState().getIn(['statuses', id]);
|
let status = getState().getIn(['statuses', id]);
|
||||||
|
|
|
@ -13,6 +13,7 @@ import classNames from 'classnames';
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
||||||
redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' },
|
redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' },
|
||||||
|
edit: { id: 'status.edit', defaultMessage: 'Edit' },
|
||||||
direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' },
|
direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' },
|
||||||
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
|
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
|
||||||
mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
|
mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
|
||||||
|
@ -126,6 +127,10 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
this.props.onDelete(this.props.status, this.context.router.history, true);
|
this.props.onDelete(this.props.status, this.context.router.history, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleEditClick = () => {
|
||||||
|
this.props.onEdit(this.props.status, this.context.router.history);
|
||||||
|
}
|
||||||
|
|
||||||
handlePinClick = () => {
|
handlePinClick = () => {
|
||||||
this.props.onPin(this.props.status);
|
this.props.onPin(this.props.status);
|
||||||
}
|
}
|
||||||
|
@ -225,6 +230,7 @@ class StatusActionBar extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (writtenByMe) {
|
if (writtenByMe) {
|
||||||
|
menu.push({ text: intl.formatMessage(messages.edit), action: this.handleEditClick });
|
||||||
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
|
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
|
||||||
menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick });
|
menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick });
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {
|
||||||
pin,
|
pin,
|
||||||
unpin,
|
unpin,
|
||||||
} from 'flavours/glitch/actions/interactions';
|
} from 'flavours/glitch/actions/interactions';
|
||||||
import { muteStatus, unmuteStatus, deleteStatus } from 'flavours/glitch/actions/statuses';
|
import { muteStatus, unmuteStatus, deleteStatus, editStatus } from 'flavours/glitch/actions/statuses';
|
||||||
import { initMuteModal } from 'flavours/glitch/actions/mutes';
|
import { initMuteModal } from 'flavours/glitch/actions/mutes';
|
||||||
import { initBlockModal } from 'flavours/glitch/actions/blocks';
|
import { initBlockModal } from 'flavours/glitch/actions/blocks';
|
||||||
import { initReport } from 'flavours/glitch/actions/reports';
|
import { initReport } from 'flavours/glitch/actions/reports';
|
||||||
|
@ -169,6 +169,10 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onEdit (status, history) {
|
||||||
|
dispatch(editStatus(status.get('id'), history));
|
||||||
|
},
|
||||||
|
|
||||||
onDirect (account, router) {
|
onDirect (account, router) {
|
||||||
dispatch(directCompose(account, router));
|
dispatch(directCompose(account, router));
|
||||||
},
|
},
|
||||||
|
|
|
@ -47,6 +47,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
preselectDate: PropTypes.instanceOf(Date),
|
preselectDate: PropTypes.instanceOf(Date),
|
||||||
isSubmitting: PropTypes.bool,
|
isSubmitting: PropTypes.bool,
|
||||||
isChangingUpload: PropTypes.bool,
|
isChangingUpload: PropTypes.bool,
|
||||||
|
isEditing: PropTypes.bool,
|
||||||
isUploading: PropTypes.bool,
|
isUploading: PropTypes.bool,
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
onSubmit: PropTypes.func,
|
onSubmit: PropTypes.func,
|
||||||
|
@ -293,6 +294,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
spoilerText,
|
spoilerText,
|
||||||
suggestions,
|
suggestions,
|
||||||
spoilersAlwaysOn,
|
spoilersAlwaysOn,
|
||||||
|
isEditing,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
const countText = this.getFulltextForCharacterCounting();
|
const countText = this.getFulltextForCharacterCounting();
|
||||||
|
@ -364,6 +366,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
<Publisher
|
<Publisher
|
||||||
countText={countText}
|
countText={countText}
|
||||||
disabled={!this.canSubmit()}
|
disabled={!this.canSubmit()}
|
||||||
|
isEditing={isEditing}
|
||||||
onSecondarySubmit={handleSecondarySubmit}
|
onSecondarySubmit={handleSecondarySubmit}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
privacy={privacy}
|
privacy={privacy}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import { length } from 'stringz';
|
import { length } from 'stringz';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ const messages = defineMessages({
|
||||||
defaultMessage: '{publish}!',
|
defaultMessage: '{publish}!',
|
||||||
id: 'compose_form.publish_loud',
|
id: 'compose_form.publish_loud',
|
||||||
},
|
},
|
||||||
|
saveChanges: { id: 'compose_form.save_changes', defaultMessage: 'Save changes' },
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @injectIntl
|
export default @injectIntl
|
||||||
|
@ -36,6 +37,7 @@ class Publisher extends ImmutablePureComponent {
|
||||||
onSubmit: PropTypes.func,
|
onSubmit: PropTypes.func,
|
||||||
privacy: PropTypes.oneOf(['direct', 'private', 'unlisted', 'public']),
|
privacy: PropTypes.oneOf(['direct', 'private', 'unlisted', 'public']),
|
||||||
sideArm: PropTypes.oneOf(['none', 'direct', 'private', 'unlisted', 'public']),
|
sideArm: PropTypes.oneOf(['none', 'direct', 'private', 'unlisted', 'public']),
|
||||||
|
isEditing: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
handleSubmit = () => {
|
handleSubmit = () => {
|
||||||
|
@ -43,7 +45,7 @@ class Publisher extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { countText, disabled, intl, onSecondarySubmit, privacy, sideArm } = this.props;
|
const { countText, disabled, intl, onSecondarySubmit, privacy, sideArm, isEditing } = this.props;
|
||||||
|
|
||||||
const diff = maxChars - length(countText || '');
|
const diff = maxChars - length(countText || '');
|
||||||
const computedClass = classNames('composer--publisher', {
|
const computedClass = classNames('composer--publisher', {
|
||||||
|
@ -51,63 +53,37 @@ class Publisher extends ImmutablePureComponent {
|
||||||
over: diff < 0,
|
over: diff < 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const privacyIcons = { direct: 'envelope', private: 'lock', public: 'globe', unlisted: 'unlock' };
|
||||||
|
|
||||||
|
let publishText;
|
||||||
|
if (isEditing) {
|
||||||
|
publishText = intl.formatMessage(messages.saveChanges);
|
||||||
|
} else if (privacy === 'private' || privacy === 'direct') {
|
||||||
|
const iconId = privacyIcons[privacy];
|
||||||
|
publishText = (
|
||||||
|
<span>
|
||||||
|
<Icon id={iconId} /> {intl.formatMessage(messages.publish)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
publishText = privacy !== 'unlisted' ? intl.formatMessage(messages.publishLoud, { publish: intl.formatMessage(messages.publish) }) : intl.formatMessage(messages.publish);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={computedClass}>
|
<div className={computedClass}>
|
||||||
{sideArm && sideArm !== 'none' ? (
|
{sideArm && !isEditing && sideArm !== 'none' ? (
|
||||||
<Button
|
<Button
|
||||||
className='side_arm'
|
className='side_arm'
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onClick={onSecondarySubmit}
|
onClick={onSecondarySubmit}
|
||||||
style={{ padding: null }}
|
style={{ padding: null }}
|
||||||
text={
|
text={<Icon id={privacyIcons[sideArm]} />}
|
||||||
<span>
|
|
||||||
<Icon
|
|
||||||
id={{
|
|
||||||
public: 'globe',
|
|
||||||
unlisted: 'unlock',
|
|
||||||
private: 'lock',
|
|
||||||
direct: 'envelope',
|
|
||||||
}[sideArm]}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
title={`${intl.formatMessage(messages.publish)}: ${intl.formatMessage({ id: `privacy.${sideArm}.short` })}`}
|
title={`${intl.formatMessage(messages.publish)}: ${intl.formatMessage({ id: `privacy.${sideArm}.short` })}`}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<Button
|
<Button
|
||||||
className='primary'
|
className='primary'
|
||||||
text={function () {
|
text={publishText}
|
||||||
switch (true) {
|
|
||||||
case !!sideArm && sideArm !== 'none':
|
|
||||||
case privacy === 'direct':
|
|
||||||
case privacy === 'private':
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
<Icon
|
|
||||||
id={{
|
|
||||||
direct: 'envelope',
|
|
||||||
private: 'lock',
|
|
||||||
public: 'globe',
|
|
||||||
unlisted: 'unlock',
|
|
||||||
}[privacy]}
|
|
||||||
/>
|
|
||||||
{' '}
|
|
||||||
<FormattedMessage {...messages.publish} />
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
case privacy === 'public':
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
<FormattedMessage
|
|
||||||
{...messages.publishLoud}
|
|
||||||
values={{ publish: <FormattedMessage {...messages.publish} /> }}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
return <span><FormattedMessage {...messages.publish} /></span>;
|
|
||||||
}
|
|
||||||
}()}
|
|
||||||
title={`${intl.formatMessage(messages.publish)}: ${intl.formatMessage({ id: `privacy.${privacy}.short` })}`}
|
title={`${intl.formatMessage(messages.publish)}: ${intl.formatMessage({ id: `privacy.${privacy}.short` })}`}
|
||||||
onClick={this.handleSubmit}
|
onClick={this.handleSubmit}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
|
@ -51,6 +51,7 @@ function mapStateToProps (state) {
|
||||||
focusDate: state.getIn(['compose', 'focusDate']),
|
focusDate: state.getIn(['compose', 'focusDate']),
|
||||||
caretPosition: state.getIn(['compose', 'caretPosition']),
|
caretPosition: state.getIn(['compose', 'caretPosition']),
|
||||||
isSubmitting: state.getIn(['compose', 'is_submitting']),
|
isSubmitting: state.getIn(['compose', 'is_submitting']),
|
||||||
|
isEditing: state.getIn(['compose', 'id']) !== null,
|
||||||
isChangingUpload: state.getIn(['compose', 'is_changing_upload']),
|
isChangingUpload: state.getIn(['compose', 'is_changing_upload']),
|
||||||
isUploading: state.getIn(['compose', 'is_uploading']),
|
isUploading: state.getIn(['compose', 'is_uploading']),
|
||||||
layout: state.getIn(['local_settings', 'layout']),
|
layout: state.getIn(['local_settings', 'layout']),
|
||||||
|
|
|
@ -1,14 +1,24 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { cancelReplyCompose } from 'flavours/glitch/actions/compose';
|
import { cancelReplyCompose } from 'flavours/glitch/actions/compose';
|
||||||
import { makeGetStatus } from 'flavours/glitch/selectors';
|
|
||||||
import ReplyIndicator from '../components/reply_indicator';
|
import ReplyIndicator from '../components/reply_indicator';
|
||||||
|
|
||||||
function makeMapStateToProps (state) {
|
const makeMapStateToProps = () => {
|
||||||
const inReplyTo = state.getIn(['compose', 'in_reply_to']);
|
const mapStateToProps = state => {
|
||||||
|
let statusId = state.getIn(['compose', 'id'], null);
|
||||||
|
let editing = true;
|
||||||
|
|
||||||
return {
|
if (statusId === null) {
|
||||||
status: inReplyTo ? state.getIn(['statuses', inReplyTo]) : null,
|
statusId = state.getIn(['compose', 'in_reply_to']);
|
||||||
|
editing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: state.getIn(['statuses', statusId]),
|
||||||
|
editing,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return mapStateToProps;
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => ({
|
const mapDispatchToProps = dispatch => ({
|
||||||
|
|
|
@ -11,6 +11,7 @@ import classNames from 'classnames';
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
delete: { id: 'status.delete', defaultMessage: 'Delete' },
|
||||||
redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' },
|
redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' },
|
||||||
|
edit: { id: 'status.edit', defaultMessage: 'Edit' },
|
||||||
direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' },
|
direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' },
|
||||||
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
|
mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' },
|
||||||
reply: { id: 'status.reply', defaultMessage: 'Reply' },
|
reply: { id: 'status.reply', defaultMessage: 'Reply' },
|
||||||
|
@ -52,6 +53,7 @@ class ActionBar extends React.PureComponent {
|
||||||
onMuteConversation: PropTypes.func,
|
onMuteConversation: PropTypes.func,
|
||||||
onBlock: PropTypes.func,
|
onBlock: PropTypes.func,
|
||||||
onDelete: PropTypes.func.isRequired,
|
onDelete: PropTypes.func.isRequired,
|
||||||
|
onEdit: PropTypes.func.isRequired,
|
||||||
onDirect: PropTypes.func.isRequired,
|
onDirect: PropTypes.func.isRequired,
|
||||||
onMention: PropTypes.func.isRequired,
|
onMention: PropTypes.func.isRequired,
|
||||||
onReport: PropTypes.func,
|
onReport: PropTypes.func,
|
||||||
|
@ -84,6 +86,10 @@ class ActionBar extends React.PureComponent {
|
||||||
this.props.onDelete(this.props.status, this.context.router.history, true);
|
this.props.onDelete(this.props.status, this.context.router.history, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleEditClick = () => {
|
||||||
|
this.props.onEdit(this.props.status, this.context.router.history);
|
||||||
|
}
|
||||||
|
|
||||||
handleDirectClick = () => {
|
handleDirectClick = () => {
|
||||||
this.props.onDirect(this.props.status.get('account'), this.context.router.history);
|
this.props.onDirect(this.props.status.get('account'), this.context.router.history);
|
||||||
}
|
}
|
||||||
|
@ -166,6 +172,7 @@ class ActionBar extends React.PureComponent {
|
||||||
|
|
||||||
menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick });
|
menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick });
|
||||||
menu.push(null);
|
menu.push(null);
|
||||||
|
menu.push({ text: intl.formatMessage(messages.edit), action: this.handleEditClick });
|
||||||
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
|
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
|
||||||
menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick });
|
menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick });
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -26,7 +26,7 @@ import {
|
||||||
directCompose,
|
directCompose,
|
||||||
} from 'flavours/glitch/actions/compose';
|
} from 'flavours/glitch/actions/compose';
|
||||||
import { changeLocalSetting } from 'flavours/glitch/actions/local_settings';
|
import { changeLocalSetting } from 'flavours/glitch/actions/local_settings';
|
||||||
import { muteStatus, unmuteStatus, deleteStatus } from 'flavours/glitch/actions/statuses';
|
import { muteStatus, unmuteStatus, deleteStatus, editStatus } from 'flavours/glitch/actions/statuses';
|
||||||
import { initMuteModal } from 'flavours/glitch/actions/mutes';
|
import { initMuteModal } from 'flavours/glitch/actions/mutes';
|
||||||
import { initBlockModal } from 'flavours/glitch/actions/blocks';
|
import { initBlockModal } from 'flavours/glitch/actions/blocks';
|
||||||
import { initReport } from 'flavours/glitch/actions/reports';
|
import { initReport } from 'flavours/glitch/actions/reports';
|
||||||
|
@ -307,6 +307,10 @@ class Status extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleEditClick = (status, history) => {
|
||||||
|
this.props.dispatch(editStatus(status.get('id'), history));
|
||||||
|
}
|
||||||
|
|
||||||
handleDirectClick = (account, router) => {
|
handleDirectClick = (account, router) => {
|
||||||
this.props.dispatch(directCompose(account, router));
|
this.props.dispatch(directCompose(account, router));
|
||||||
}
|
}
|
||||||
|
@ -585,6 +589,7 @@ class Status extends ImmutablePureComponent {
|
||||||
onReblog={this.handleReblogClick}
|
onReblog={this.handleReblogClick}
|
||||||
onBookmark={this.handleBookmarkClick}
|
onBookmark={this.handleBookmarkClick}
|
||||||
onDelete={this.handleDeleteClick}
|
onDelete={this.handleDeleteClick}
|
||||||
|
onEdit={this.handleEditClick}
|
||||||
onDirect={this.handleDirectClick}
|
onDirect={this.handleDirectClick}
|
||||||
onMention={this.handleMentionClick}
|
onMention={this.handleMentionClick}
|
||||||
onMute={this.handleMuteClick}
|
onMute={this.handleMuteClick}
|
||||||
|
|
|
@ -46,6 +46,7 @@ import {
|
||||||
INIT_MEDIA_EDIT_MODAL,
|
INIT_MEDIA_EDIT_MODAL,
|
||||||
COMPOSE_CHANGE_MEDIA_DESCRIPTION,
|
COMPOSE_CHANGE_MEDIA_DESCRIPTION,
|
||||||
COMPOSE_CHANGE_MEDIA_FOCUS,
|
COMPOSE_CHANGE_MEDIA_FOCUS,
|
||||||
|
COMPOSE_SET_STATUS,
|
||||||
} from 'flavours/glitch/actions/compose';
|
} from 'flavours/glitch/actions/compose';
|
||||||
import { TIMELINE_DELETE } from 'flavours/glitch/actions/timelines';
|
import { TIMELINE_DELETE } from 'flavours/glitch/actions/timelines';
|
||||||
import { STORE_HYDRATE } from 'flavours/glitch/actions/store';
|
import { STORE_HYDRATE } from 'flavours/glitch/actions/store';
|
||||||
|
@ -75,6 +76,7 @@ const initialState = ImmutableMap({
|
||||||
spoiler: false,
|
spoiler: false,
|
||||||
spoiler_text: '',
|
spoiler_text: '',
|
||||||
privacy: null,
|
privacy: null,
|
||||||
|
id: null,
|
||||||
content_type: defaultContentType || 'text/plain',
|
content_type: defaultContentType || 'text/plain',
|
||||||
text: '',
|
text: '',
|
||||||
focusDate: null,
|
focusDate: null,
|
||||||
|
@ -160,6 +162,7 @@ function apiStatusToTextHashtags (state, status) {
|
||||||
|
|
||||||
function clearAll(state) {
|
function clearAll(state) {
|
||||||
return state.withMutations(map => {
|
return state.withMutations(map => {
|
||||||
|
map.set('id', null);
|
||||||
map.set('text', '');
|
map.set('text', '');
|
||||||
if (defaultContentType) map.set('content_type', defaultContentType);
|
if (defaultContentType) map.set('content_type', defaultContentType);
|
||||||
map.set('spoiler', false);
|
map.set('spoiler', false);
|
||||||
|
@ -400,6 +403,7 @@ export default function compose(state = initialState, action) {
|
||||||
.set('elefriend', (state.get('elefriend') + 1) % totalElefriends);
|
.set('elefriend', (state.get('elefriend') + 1) % totalElefriends);
|
||||||
case COMPOSE_REPLY:
|
case COMPOSE_REPLY:
|
||||||
return state.withMutations(map => {
|
return state.withMutations(map => {
|
||||||
|
map.set('id', null);
|
||||||
map.set('in_reply_to', action.status.get('id'));
|
map.set('in_reply_to', action.status.get('id'));
|
||||||
map.set('text', statusToTextMentions(state, action.status));
|
map.set('text', statusToTextMentions(state, action.status));
|
||||||
map.set('privacy', privacyPreference(action.status.get('visibility'), state.get('default_privacy')));
|
map.set('privacy', privacyPreference(action.status.get('visibility'), state.get('default_privacy')));
|
||||||
|
@ -434,6 +438,7 @@ export default function compose(state = initialState, action) {
|
||||||
map.set('spoiler', false);
|
map.set('spoiler', false);
|
||||||
map.set('spoiler_text', '');
|
map.set('spoiler_text', '');
|
||||||
map.set('privacy', state.get('default_privacy'));
|
map.set('privacy', state.get('default_privacy'));
|
||||||
|
map.set('id', null);
|
||||||
map.set('poll', null);
|
map.set('poll', null);
|
||||||
map.update(
|
map.update(
|
||||||
'advanced_options',
|
'advanced_options',
|
||||||
|
@ -565,6 +570,34 @@ export default function compose(state = initialState, action) {
|
||||||
map.set('spoiler_text', '');
|
map.set('spoiler_text', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action.status.get('poll')) {
|
||||||
|
map.set('poll', ImmutableMap({
|
||||||
|
options: action.status.getIn(['poll', 'options']).map(x => x.get('title')),
|
||||||
|
multiple: action.status.getIn(['poll', 'multiple']),
|
||||||
|
expires_in: expiresInFromExpiresAt(action.status.getIn(['poll', 'expires_at'])),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
case COMPOSE_SET_STATUS:
|
||||||
|
return state.withMutations(map => {
|
||||||
|
map.set('id', action.status.get('id'));
|
||||||
|
map.set('text', action.text);
|
||||||
|
map.set('in_reply_to', action.status.get('in_reply_to_id'));
|
||||||
|
map.set('privacy', action.status.get('visibility'));
|
||||||
|
map.set('media_attachments', action.status.get('media_attachments'));
|
||||||
|
map.set('focusDate', new Date());
|
||||||
|
map.set('caretPosition', null);
|
||||||
|
map.set('idempotencyKey', uuid());
|
||||||
|
map.set('sensitive', action.status.get('sensitive'));
|
||||||
|
|
||||||
|
if (action.spoiler_text.length > 0) {
|
||||||
|
map.set('spoiler', true);
|
||||||
|
map.set('spoiler_text', action.spoiler_text);
|
||||||
|
} else {
|
||||||
|
map.set('spoiler', false);
|
||||||
|
map.set('spoiler_text', '');
|
||||||
|
}
|
||||||
|
|
||||||
if (action.status.get('poll')) {
|
if (action.status.get('poll')) {
|
||||||
map.set('poll', ImmutableMap({
|
map.set('poll', ImmutableMap({
|
||||||
options: action.status.getIn(['poll', 'options']).map(x => x.get('title')),
|
options: action.status.getIn(['poll', 'options']).map(x => x.get('title')),
|
||||||
|
|
Reference in New Issue