diff --git a/app/javascript/gabsocial/actions/compose.js b/app/javascript/gabsocial/actions/compose.js index bd5424fc..a52dc427 100644 --- a/app/javascript/gabsocial/actions/compose.js +++ b/app/javascript/gabsocial/actions/compose.js @@ -151,7 +151,13 @@ export function submitCompose(routerHistory, group) { dispatch(submitComposeRequest()); dispatch(closeModal()); - api(getState).post('/api/v1/statuses', { + const id = getState().getIn(['compose', 'id']); + const endpoint = id === null + ? '/api/v1/statuses' + : `/api/v1/statuses/${id}`; + const method = id === null ? 'post' : 'put'; + + api(getState)[method](endpoint, { status, in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null), quote_of_id: getState().getIn(['compose', 'quote_of_id'], null), diff --git a/app/javascript/gabsocial/actions/statuses.js b/app/javascript/gabsocial/actions/statuses.js index 06b40542..090569e4 100644 --- a/app/javascript/gabsocial/actions/statuses.js +++ b/app/javascript/gabsocial/actions/statuses.js @@ -140,6 +140,18 @@ export function redraft(status, raw_text) { }; }; +export function editStatus(status) { + return dispatch => { + dispatch({ + type: REDRAFT, + edit: true, + status, + }); + + dispatch(openModal('COMPOSE')); + }; +}; + export function deleteStatus(id, routerHistory, withRedraft = false) { return (dispatch, getState) => { if (!me) return; diff --git a/app/javascript/gabsocial/components/status.js b/app/javascript/gabsocial/components/status.js index ec4b0263..58389e1a 100644 --- a/app/javascript/gabsocial/components/status.js +++ b/app/javascript/gabsocial/components/status.js @@ -71,6 +71,7 @@ class Status extends ImmutablePureComponent { onFavourite: PropTypes.func, onReblog: PropTypes.func, onDelete: PropTypes.func, + onEdit: PropTypes.func, onDirect: PropTypes.func, onMention: PropTypes.func, onPin: PropTypes.func, diff --git a/app/javascript/gabsocial/components/status_action_bar.js b/app/javascript/gabsocial/components/status_action_bar.js index 42dfa150..90e069ff 100644 --- a/app/javascript/gabsocial/components/status_action_bar.js +++ b/app/javascript/gabsocial/components/status_action_bar.js @@ -14,6 +14,7 @@ import { Link } from 'react-router-dom'; const messages = defineMessages({ delete: { id: 'status.delete', defaultMessage: 'Delete' }, redraft: { id: 'status.redraft', defaultMessage: 'Delete & re-draft' }, + edit: { id: 'status.edit', defaultMessage: 'Edit' }, direct: { id: 'status.direct', defaultMessage: 'Direct message @{name}' }, mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, @@ -116,6 +117,10 @@ class StatusActionBar extends ImmutablePureComponent { this.props.onDelete(this.props.status, this.context.router.history, true); } + handleEditClick = () => { + this.props.onEdit(this.props.status); + } + handlePinClick = () => { this.props.onPin(this.props.status); } @@ -218,6 +223,7 @@ class StatusActionBar extends ImmutablePureComponent { 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.edit), action: this.handleEditClick }); } else { menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick }); //menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick }); diff --git a/app/javascript/gabsocial/containers/status_container.js b/app/javascript/gabsocial/containers/status_container.js index 707c90e6..7a4b41bb 100644 --- a/app/javascript/gabsocial/containers/status_container.js +++ b/app/javascript/gabsocial/containers/status_container.js @@ -21,6 +21,7 @@ import { muteStatus, unmuteStatus, deleteStatus, + editStatus, hideStatus, revealStatus, } from '../actions/statuses'; @@ -141,6 +142,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ } }, + onEdit (status) { + dispatch(editStatus(status)); + }, + onDirect (account, router) { dispatch(directCompose(account, router)); }, diff --git a/app/javascript/gabsocial/features/ui/components/compose_modal.js b/app/javascript/gabsocial/features/ui/components/compose_modal.js index 865bdec3..6d6a1940 100644 --- a/app/javascript/gabsocial/features/ui/components/compose_modal.js +++ b/app/javascript/gabsocial/features/ui/components/compose_modal.js @@ -20,6 +20,7 @@ const mapStateToProps = state => { return { account: state.getIn(['accounts', me]), composeText: state.getIn(['compose', 'text']), + composeId: state.getIn(['compose', 'id']), }; }; @@ -34,9 +35,9 @@ class ComposeModal extends ImmutablePureComponent { }; onClickClose = () => { - const {composeText, dispatch, onClose, intl} = this.props; + const {composeText, composeId, dispatch, onClose, intl} = this.props; - if (composeText) { + if (!composeId && composeText) { dispatch(openModal('CONFIRM', { message: , confirm: intl.formatMessage(messages.confirm), diff --git a/app/javascript/gabsocial/reducers/compose.js b/app/javascript/gabsocial/reducers/compose.js index d65b2998..6b7a9a79 100644 --- a/app/javascript/gabsocial/reducers/compose.js +++ b/app/javascript/gabsocial/reducers/compose.js @@ -46,6 +46,7 @@ import { me } from '../initial_state'; import { unescapeHTML } from '../utils/html'; const initialState = ImmutableMap({ + id: null, mounted: 0, sensitive: false, spoiler: false, @@ -279,6 +280,7 @@ export default function compose(state = initialState, action) { case COMPOSE_REPLY_CANCEL: case COMPOSE_RESET: return state.withMutations(map => { + map.set('id', null); map.set('quote_of_id', null); map.set('in_reply_to', null); map.set('text', ''); @@ -353,6 +355,10 @@ export default function compose(state = initialState, action) { })); case REDRAFT: return state.withMutations(map => { + if (action.edit === true) { + map.set('id', action.status.get('id')); + } + map.set('text', action.raw_text || unescapeHTML(expandMentions(action.status))); map.set('in_reply_to', action.status.get('in_reply_to_id')); map.set('quote_of_id', action.status.get('quote_of_id'));