diff --git a/app/javascript/flavours/glitch/actions/compose.js b/app/javascript/flavours/glitch/actions/compose.js index f117ce771..2fb97fa17 100644 --- a/app/javascript/flavours/glitch/actions/compose.js +++ b/app/javascript/flavours/glitch/actions/compose.js @@ -46,6 +46,7 @@ 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'; +export const COMPOSE_CONTENT_TYPE_CHANGE = 'COMPOSE_CONTENT_TYPE_CHANGE'; export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT'; @@ -147,6 +148,7 @@ export function submitCompose(routerHistory) { } api(getState).post('/api/v1/statuses', { status, + 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), @@ -517,6 +519,13 @@ export function changeComposeVisibility(value) { }; }; +export function changeComposeContentType(value) { + return { + type: COMPOSE_CONTENT_TYPE_CHANGE, + value, + }; +}; + export function insertEmojiCompose(position, emoji) { return { type: COMPOSE_EMOJI_INSERT, diff --git a/app/javascript/flavours/glitch/features/compose/components/compose_form.js b/app/javascript/flavours/glitch/features/compose/components/compose_form.js index e8f000b1e..4e93e2d84 100644 --- a/app/javascript/flavours/glitch/features/compose/components/compose_form.js +++ b/app/javascript/flavours/glitch/features/compose/components/compose_form.js @@ -38,6 +38,7 @@ class ComposeForm extends ImmutablePureComponent { suggestions: ImmutablePropTypes.list, spoiler: PropTypes.bool, privacy: PropTypes.string, + contentType: PropTypes.string, spoilerText: PropTypes.string, focusDate: PropTypes.instanceOf(Date), caretPosition: PropTypes.number, @@ -66,6 +67,7 @@ class ComposeForm extends ImmutablePureComponent { preselectOnReply: PropTypes.bool, onChangeSpoilerness: PropTypes.func, onChangeVisibility: PropTypes.func, + onChangeContentType: PropTypes.func, onMount: PropTypes.func, onUnmount: PropTypes.func, onPaste: PropTypes.func, @@ -285,10 +287,12 @@ class ComposeForm extends ImmutablePureComponent { media, onChangeSpoilerness, onChangeVisibility, + onChangeContentType, onClearSuggestions, onFetchSuggestions, onPaste, privacy, + contentType, sensitive, showSearch, sideArm, @@ -356,9 +360,11 @@ class ComposeForm extends ImmutablePureComponent { advancedOptions={advancedOptions} disabled={isSubmitting} onChangeVisibility={onChangeVisibility} + onChangeContentType={onChangeContentType} onToggleSpoiler={spoilersAlwaysOn ? null : onChangeSpoilerness} onUpload={onPaste} privacy={privacy} + contentType={contentType} sensitive={sensitive || (spoilersAlwaysOn && spoilerText && spoilerText.length > 0)} spoiler={spoilersAlwaysOn ? (spoilerText && spoilerText.length > 0) : spoiler} /> @@ -369,6 +375,7 @@ class ComposeForm extends ImmutablePureComponent { onSecondarySubmit={handleSecondarySubmit} onSubmit={handleSubmit} privacy={privacy} + contentType={contentType} sideArm={sideArm} /> diff --git a/app/javascript/flavours/glitch/features/compose/components/options.js b/app/javascript/flavours/glitch/features/compose/components/options.js index ee9730961..908126c6f 100644 --- a/app/javascript/flavours/glitch/features/compose/components/options.js +++ b/app/javascript/flavours/glitch/features/compose/components/options.js @@ -29,6 +29,10 @@ const messages = defineMessages({ defaultMessage: 'Adjust status privacy', id: 'privacy.change', }, + content_type: { + defaultMessage: 'Content type', + id: 'content-type.change', + }, direct_long: { defaultMessage: 'Post to mentioned users only', id: 'privacy.direct.long', @@ -41,6 +45,10 @@ const messages = defineMessages({ defaultMessage: 'Draw something', id: 'compose.attach.doodle', }, + html: { + defaultMessage: 'HTML', + id: 'compose.content-type.html', + }, local_only_long: { defaultMessage: 'Do not post to other instances', id: 'advanced_options.local-only.long', @@ -49,6 +57,14 @@ const messages = defineMessages({ defaultMessage: 'Local-only', id: 'advanced_options.local-only.short', }, + markdown: { + defaultMessage: 'Markdown', + id: 'compose.content-type.markdown', + }, + plain: { + defaultMessage: 'Plain text', + id: 'compose.content-type.plain', + }, private_long: { defaultMessage: 'Post to followers only', id: 'privacy.private.long', @@ -113,6 +129,7 @@ class ComposerOptions extends ImmutablePureComponent { intl: PropTypes.object.isRequired, onChangeAdvancedOption: PropTypes.func, onChangeVisibility: PropTypes.func, + onChangeContentType: PropTypes.func, onTogglePoll: PropTypes.func, onDoodleOpen: PropTypes.func, onModalClose: PropTypes.func, @@ -120,6 +137,7 @@ class ComposerOptions extends ImmutablePureComponent { onToggleSpoiler: PropTypes.func, onUpload: PropTypes.func, privacy: PropTypes.string, + contentType: PropTypes.string, resetFileKey: PropTypes.number, spoiler: PropTypes.bool, }; @@ -162,6 +180,7 @@ class ComposerOptions extends ImmutablePureComponent { const { acceptContentTypes, advancedOptions, + contentType, disabled, allowMedia, hasMedia, @@ -169,6 +188,7 @@ class ComposerOptions extends ImmutablePureComponent { hasPoll, intl, onChangeAdvancedOption, + onChangeContentType, onChangeVisibility, onTogglePoll, onModalClose, @@ -208,6 +228,24 @@ class ComposerOptions extends ImmutablePureComponent { }, }; + const contentTypeItems = { + plain: { + icon: 'file', + name: 'text/plain', + text: , + }, + html: { + icon: 'file-text', + name: 'text/html', + text: , + }, + markdown: { + icon: 'file-text', + name: 'text/markdown', + text: , + }, + }; + // The result. return (
@@ -272,6 +310,19 @@ class ComposerOptions extends ImmutablePureComponent { title={intl.formatMessage(messages.change_privacy)} value={privacy} /> + {onToggleSpoiler && ( ({ dispatch(changeComposeSpoilerText(text)); }, + onChangeContentType(value) { + dispatch(changeComposeContentType(value)); + }, + onPaste(files) { dispatch(uploadCompose(files)); }, diff --git a/app/javascript/flavours/glitch/features/compose/index.js b/app/javascript/flavours/glitch/features/compose/index.js index a7795a04d..e60eedfd9 100644 --- a/app/javascript/flavours/glitch/features/compose/index.js +++ b/app/javascript/flavours/glitch/features/compose/index.js @@ -29,7 +29,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({ }, }); -export default @connect(mapStateToProps, mapDispatchToProps) +export default @connect(mapStateToProps) @injectIntl class Compose extends React.PureComponent { static propTypes = { diff --git a/app/javascript/flavours/glitch/reducers/compose.js b/app/javascript/flavours/glitch/reducers/compose.js index bc1785a48..516da859a 100644 --- a/app/javascript/flavours/glitch/reducers/compose.js +++ b/app/javascript/flavours/glitch/reducers/compose.js @@ -25,6 +25,7 @@ import { COMPOSE_SPOILERNESS_CHANGE, COMPOSE_SPOILER_TEXT_CHANGE, COMPOSE_VISIBILITY_CHANGE, + COMPOSE_CONTENT_TYPE_CHANGE, COMPOSE_EMOJI_INSERT, COMPOSE_UPLOAD_CHANGE_REQUEST, COMPOSE_UPLOAD_CHANGE_SUCCESS, @@ -66,6 +67,7 @@ const initialState = ImmutableMap({ spoiler: false, spoiler_text: '', privacy: null, + content_type: 'text/plain', text: '', focusDate: null, caretPosition: null, @@ -310,6 +312,10 @@ export default function compose(state = initialState, action) { return state .set('privacy', action.value) .set('idempotencyKey', uuid()); + case COMPOSE_CONTENT_TYPE_CHANGE: + return state + .set('content_type', action.value) + .set('idempotencyKey', uuid()); case COMPOSE_CHANGE: return state .set('text', action.text)