diff --git a/app/assets/javascripts/components/actions/compose.jsx b/app/assets/javascripts/components/actions/compose.jsx
index 05674ba898..6d0188166e 100644
--- a/app/assets/javascripts/components/actions/compose.jsx
+++ b/app/assets/javascripts/components/actions/compose.jsx
@@ -23,6 +23,8 @@ export const COMPOSE_MOUNT = 'COMPOSE_MOUNT';
export const COMPOSE_UNMOUNT = 'COMPOSE_UNMOUNT';
export const COMPOSE_SENSITIVITY_CHANGE = 'COMPOSE_SENSITIVITY_CHANGE';
+export const COMPOSE_SPOILERNESS_CHANGE = 'COMPOSE_SPOILERNESS_CHANGE';
+export const COMPOSE_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE';
export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE';
export const COMPOSE_LISTABILITY_CHANGE = 'COMPOSE_LISTABILITY_CHANGE';
@@ -68,6 +70,7 @@ export function submitCompose() {
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
media_ids: getState().getIn(['compose', 'media_attachments']).map(item => item.get('id')),
sensitive: getState().getIn(['compose', 'sensitive']),
+ spoiler_text: getState().getIn(['compose', 'spoiler_text'], ''),
visibility: getState().getIn(['compose', 'private']) ? 'private' : (getState().getIn(['compose', 'unlisted']) ? 'unlisted' : 'public')
}).then(function (response) {
dispatch(submitComposeSuccess({ ...response.data }));
@@ -218,6 +221,20 @@ export function changeComposeSensitivity(checked) {
};
};
+export function changeComposeSpoilerness(checked) {
+ return {
+ type: COMPOSE_SPOILERNESS_CHANGE,
+ checked
+ };
+};
+
+export function changeComposeSpoilerText(text) {
+ return {
+ type: COMPOSE_SPOILER_TEXT_CHANGE,
+ text
+ };
+};
+
export function changeComposeVisibility(checked) {
return {
type: COMPOSE_VISIBILITY_CHANGE,
diff --git a/app/assets/javascripts/components/components/status_content.jsx b/app/assets/javascripts/components/components/status_content.jsx
index 1ee720c9bd..ff90226d8f 100644
--- a/app/assets/javascripts/components/components/status_content.jsx
+++ b/app/assets/javascripts/components/components/status_content.jsx
@@ -1,6 +1,7 @@
import ImmutablePropTypes from 'react-immutable-proptypes';
import PureRenderMixin from 'react-addons-pure-render-mixin';
import emojify from '../emoji';
+import { FormattedMessage } from 'react-intl';
const StatusContent = React.createClass({
@@ -13,6 +14,12 @@ const StatusContent = React.createClass({
onClick: React.PropTypes.func
},
+ getInitialState () {
+ return {
+ hidden: true
+ };
+ },
+
mixins: [PureRenderMixin],
componentDidMount () {
@@ -69,20 +76,40 @@ const StatusContent = React.createClass({
this.startXY = null;
},
+ handleSpoilerClick () {
+ this.setState({ hidden: !this.state.hidden });
+ },
+
render () {
const { status } = this.props;
+ const { hidden } = this.state;
const content = { __html: emojify(status.get('content')) };
+ const spoilerContent = { __html: emojify(status.get('spoiler_text')) };
- return (
-
- );
+ if (status.get('spoiler_text').length > 0) {
+ const toggleText = hidden ? : ;
+
+ return (
+
+ );
+ } else {
+ return (
+
+ );
+ }
},
});
diff --git a/app/assets/javascripts/components/features/compose/components/compose_form.jsx b/app/assets/javascripts/components/features/compose/components/compose_form.jsx
index 80cb38e160..48363a9687 100644
--- a/app/assets/javascripts/components/features/compose/components/compose_form.jsx
+++ b/app/assets/javascripts/components/features/compose/components/compose_form.jsx
@@ -14,6 +14,7 @@ import { Motion, spring } from 'react-motion';
const messages = defineMessages({
placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What is on your mind?' },
+ spoiler_placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Content warning' },
publish: { id: 'compose_form.publish', defaultMessage: 'Publish' }
});
@@ -25,6 +26,8 @@ const ComposeForm = React.createClass({
suggestion_token: React.PropTypes.string,
suggestions: ImmutablePropTypes.list,
sensitive: React.PropTypes.bool,
+ spoiler: React.PropTypes.bool,
+ spoiler_text: React.PropTypes.string,
unlisted: React.PropTypes.bool,
private: React.PropTypes.bool,
fileDropDate: React.PropTypes.instanceOf(Date),
@@ -40,6 +43,8 @@ const ComposeForm = React.createClass({
onFetchSuggestions: React.PropTypes.func.isRequired,
onSuggestionSelected: React.PropTypes.func.isRequired,
onChangeSensitivity: React.PropTypes.func.isRequired,
+ onChangeSpoilerness: React.PropTypes.func.isRequired,
+ onChangeSpoilerText: React.PropTypes.func.isRequired,
onChangeVisibility: React.PropTypes.func.isRequired,
onChangeListability: React.PropTypes.func.isRequired,
},
@@ -77,6 +82,15 @@ const ComposeForm = React.createClass({
this.props.onChangeSensitivity(e.target.checked);
},
+ handleChangeSpoilerness (e) {
+ this.props.onChangeSpoilerness(e.target.checked);
+ this.props.onChangeSpoilerText('');
+ },
+
+ handleChangeSpoilerText (e) {
+ this.props.onChangeSpoilerText(e.target.value);
+ },
+
handleChangeVisibility (e) {
this.props.onChangeVisibility(e.target.checked);
},
@@ -115,6 +129,14 @@ const ComposeForm = React.createClass({
return (
+
+ {({ opacity, height }) =>
+
+
+
+ }
+
+
{replyArea}
-
+
@@ -142,6 +164,11 @@ const ComposeForm = React.createClass({
+
+
{({ opacity, height }) =>