Add status content type dropdown to compose box.
Signed-off-by: Thibaut Girka <thib@sitedethib.com>pull/1053/head
parent
14d7ddcb1c
commit
f34a402a94
|
@ -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_SPOILER_TEXT_CHANGE = 'COMPOSE_SPOILER_TEXT_CHANGE';
|
||||||
export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE';
|
export const COMPOSE_VISIBILITY_CHANGE = 'COMPOSE_VISIBILITY_CHANGE';
|
||||||
export const COMPOSE_LISTABILITY_CHANGE = 'COMPOSE_LISTABILITY_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';
|
export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT';
|
||||||
|
|
||||||
|
@ -147,6 +148,7 @@ export function submitCompose(routerHistory) {
|
||||||
}
|
}
|
||||||
api(getState).post('/api/v1/statuses', {
|
api(getState).post('/api/v1/statuses', {
|
||||||
status,
|
status,
|
||||||
|
content_type: getState().getIn(['compose', 'content_type']),
|
||||||
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
||||||
media_ids: media.map(item => item.get('id')),
|
media_ids: media.map(item => item.get('id')),
|
||||||
sensitive: getState().getIn(['compose', 'sensitive']) || (spoilerText.length > 0 && media.size !== 0),
|
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) {
|
export function insertEmojiCompose(position, emoji) {
|
||||||
return {
|
return {
|
||||||
type: COMPOSE_EMOJI_INSERT,
|
type: COMPOSE_EMOJI_INSERT,
|
||||||
|
|
|
@ -38,6 +38,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
suggestions: ImmutablePropTypes.list,
|
suggestions: ImmutablePropTypes.list,
|
||||||
spoiler: PropTypes.bool,
|
spoiler: PropTypes.bool,
|
||||||
privacy: PropTypes.string,
|
privacy: PropTypes.string,
|
||||||
|
contentType: PropTypes.string,
|
||||||
spoilerText: PropTypes.string,
|
spoilerText: PropTypes.string,
|
||||||
focusDate: PropTypes.instanceOf(Date),
|
focusDate: PropTypes.instanceOf(Date),
|
||||||
caretPosition: PropTypes.number,
|
caretPosition: PropTypes.number,
|
||||||
|
@ -66,6 +67,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
preselectOnReply: PropTypes.bool,
|
preselectOnReply: PropTypes.bool,
|
||||||
onChangeSpoilerness: PropTypes.func,
|
onChangeSpoilerness: PropTypes.func,
|
||||||
onChangeVisibility: PropTypes.func,
|
onChangeVisibility: PropTypes.func,
|
||||||
|
onChangeContentType: PropTypes.func,
|
||||||
onMount: PropTypes.func,
|
onMount: PropTypes.func,
|
||||||
onUnmount: PropTypes.func,
|
onUnmount: PropTypes.func,
|
||||||
onPaste: PropTypes.func,
|
onPaste: PropTypes.func,
|
||||||
|
@ -285,10 +287,12 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
media,
|
media,
|
||||||
onChangeSpoilerness,
|
onChangeSpoilerness,
|
||||||
onChangeVisibility,
|
onChangeVisibility,
|
||||||
|
onChangeContentType,
|
||||||
onClearSuggestions,
|
onClearSuggestions,
|
||||||
onFetchSuggestions,
|
onFetchSuggestions,
|
||||||
onPaste,
|
onPaste,
|
||||||
privacy,
|
privacy,
|
||||||
|
contentType,
|
||||||
sensitive,
|
sensitive,
|
||||||
showSearch,
|
showSearch,
|
||||||
sideArm,
|
sideArm,
|
||||||
|
@ -356,9 +360,11 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
advancedOptions={advancedOptions}
|
advancedOptions={advancedOptions}
|
||||||
disabled={isSubmitting}
|
disabled={isSubmitting}
|
||||||
onChangeVisibility={onChangeVisibility}
|
onChangeVisibility={onChangeVisibility}
|
||||||
|
onChangeContentType={onChangeContentType}
|
||||||
onToggleSpoiler={spoilersAlwaysOn ? null : onChangeSpoilerness}
|
onToggleSpoiler={spoilersAlwaysOn ? null : onChangeSpoilerness}
|
||||||
onUpload={onPaste}
|
onUpload={onPaste}
|
||||||
privacy={privacy}
|
privacy={privacy}
|
||||||
|
contentType={contentType}
|
||||||
sensitive={sensitive || (spoilersAlwaysOn && spoilerText && spoilerText.length > 0)}
|
sensitive={sensitive || (spoilersAlwaysOn && spoilerText && spoilerText.length > 0)}
|
||||||
spoiler={spoilersAlwaysOn ? (spoilerText && spoilerText.length > 0) : spoiler}
|
spoiler={spoilersAlwaysOn ? (spoilerText && spoilerText.length > 0) : spoiler}
|
||||||
/>
|
/>
|
||||||
|
@ -369,6 +375,7 @@ class ComposeForm extends ImmutablePureComponent {
|
||||||
onSecondarySubmit={handleSecondarySubmit}
|
onSecondarySubmit={handleSecondarySubmit}
|
||||||
onSubmit={handleSubmit}
|
onSubmit={handleSubmit}
|
||||||
privacy={privacy}
|
privacy={privacy}
|
||||||
|
contentType={contentType}
|
||||||
sideArm={sideArm}
|
sideArm={sideArm}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -29,6 +29,10 @@ const messages = defineMessages({
|
||||||
defaultMessage: 'Adjust status privacy',
|
defaultMessage: 'Adjust status privacy',
|
||||||
id: 'privacy.change',
|
id: 'privacy.change',
|
||||||
},
|
},
|
||||||
|
content_type: {
|
||||||
|
defaultMessage: 'Content type',
|
||||||
|
id: 'content-type.change',
|
||||||
|
},
|
||||||
direct_long: {
|
direct_long: {
|
||||||
defaultMessage: 'Post to mentioned users only',
|
defaultMessage: 'Post to mentioned users only',
|
||||||
id: 'privacy.direct.long',
|
id: 'privacy.direct.long',
|
||||||
|
@ -41,6 +45,10 @@ const messages = defineMessages({
|
||||||
defaultMessage: 'Draw something',
|
defaultMessage: 'Draw something',
|
||||||
id: 'compose.attach.doodle',
|
id: 'compose.attach.doodle',
|
||||||
},
|
},
|
||||||
|
html: {
|
||||||
|
defaultMessage: 'HTML',
|
||||||
|
id: 'compose.content-type.html',
|
||||||
|
},
|
||||||
local_only_long: {
|
local_only_long: {
|
||||||
defaultMessage: 'Do not post to other instances',
|
defaultMessage: 'Do not post to other instances',
|
||||||
id: 'advanced_options.local-only.long',
|
id: 'advanced_options.local-only.long',
|
||||||
|
@ -49,6 +57,14 @@ const messages = defineMessages({
|
||||||
defaultMessage: 'Local-only',
|
defaultMessage: 'Local-only',
|
||||||
id: 'advanced_options.local-only.short',
|
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: {
|
private_long: {
|
||||||
defaultMessage: 'Post to followers only',
|
defaultMessage: 'Post to followers only',
|
||||||
id: 'privacy.private.long',
|
id: 'privacy.private.long',
|
||||||
|
@ -113,6 +129,7 @@ class ComposerOptions extends ImmutablePureComponent {
|
||||||
intl: PropTypes.object.isRequired,
|
intl: PropTypes.object.isRequired,
|
||||||
onChangeAdvancedOption: PropTypes.func,
|
onChangeAdvancedOption: PropTypes.func,
|
||||||
onChangeVisibility: PropTypes.func,
|
onChangeVisibility: PropTypes.func,
|
||||||
|
onChangeContentType: PropTypes.func,
|
||||||
onTogglePoll: PropTypes.func,
|
onTogglePoll: PropTypes.func,
|
||||||
onDoodleOpen: PropTypes.func,
|
onDoodleOpen: PropTypes.func,
|
||||||
onModalClose: PropTypes.func,
|
onModalClose: PropTypes.func,
|
||||||
|
@ -120,6 +137,7 @@ class ComposerOptions extends ImmutablePureComponent {
|
||||||
onToggleSpoiler: PropTypes.func,
|
onToggleSpoiler: PropTypes.func,
|
||||||
onUpload: PropTypes.func,
|
onUpload: PropTypes.func,
|
||||||
privacy: PropTypes.string,
|
privacy: PropTypes.string,
|
||||||
|
contentType: PropTypes.string,
|
||||||
resetFileKey: PropTypes.number,
|
resetFileKey: PropTypes.number,
|
||||||
spoiler: PropTypes.bool,
|
spoiler: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
@ -162,6 +180,7 @@ class ComposerOptions extends ImmutablePureComponent {
|
||||||
const {
|
const {
|
||||||
acceptContentTypes,
|
acceptContentTypes,
|
||||||
advancedOptions,
|
advancedOptions,
|
||||||
|
contentType,
|
||||||
disabled,
|
disabled,
|
||||||
allowMedia,
|
allowMedia,
|
||||||
hasMedia,
|
hasMedia,
|
||||||
|
@ -169,6 +188,7 @@ class ComposerOptions extends ImmutablePureComponent {
|
||||||
hasPoll,
|
hasPoll,
|
||||||
intl,
|
intl,
|
||||||
onChangeAdvancedOption,
|
onChangeAdvancedOption,
|
||||||
|
onChangeContentType,
|
||||||
onChangeVisibility,
|
onChangeVisibility,
|
||||||
onTogglePoll,
|
onTogglePoll,
|
||||||
onModalClose,
|
onModalClose,
|
||||||
|
@ -208,6 +228,24 @@ class ComposerOptions extends ImmutablePureComponent {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const contentTypeItems = {
|
||||||
|
plain: {
|
||||||
|
icon: 'file',
|
||||||
|
name: 'text/plain',
|
||||||
|
text: <FormattedMessage {...messages.plain} />,
|
||||||
|
},
|
||||||
|
html: {
|
||||||
|
icon: 'file-text',
|
||||||
|
name: 'text/html',
|
||||||
|
text: <FormattedMessage {...messages.html} />,
|
||||||
|
},
|
||||||
|
markdown: {
|
||||||
|
icon: 'file-text',
|
||||||
|
name: 'text/markdown',
|
||||||
|
text: <FormattedMessage {...messages.markdown} />,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// The result.
|
// The result.
|
||||||
return (
|
return (
|
||||||
<div className='composer--options'>
|
<div className='composer--options'>
|
||||||
|
@ -272,6 +310,19 @@ class ComposerOptions extends ImmutablePureComponent {
|
||||||
title={intl.formatMessage(messages.change_privacy)}
|
title={intl.formatMessage(messages.change_privacy)}
|
||||||
value={privacy}
|
value={privacy}
|
||||||
/>
|
/>
|
||||||
|
<Dropdown
|
||||||
|
icon="code"
|
||||||
|
items={[
|
||||||
|
contentTypeItems.plain,
|
||||||
|
contentTypeItems.html,
|
||||||
|
contentTypeItems.markdown,
|
||||||
|
]}
|
||||||
|
onChange={onChangeContentType}
|
||||||
|
onModalClose={onModalClose}
|
||||||
|
onModalOpen={onModalOpen}
|
||||||
|
title={intl.formatMessage(messages.content_type)}
|
||||||
|
value={contentType}
|
||||||
|
/>
|
||||||
{onToggleSpoiler && (
|
{onToggleSpoiler && (
|
||||||
<TextIconButton
|
<TextIconButton
|
||||||
active={spoiler}
|
active={spoiler}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
changeComposeSpoilerText,
|
changeComposeSpoilerText,
|
||||||
changeComposeSpoilerness,
|
changeComposeSpoilerness,
|
||||||
changeComposeVisibility,
|
changeComposeVisibility,
|
||||||
|
changeComposeContentType,
|
||||||
clearComposeSuggestions,
|
clearComposeSuggestions,
|
||||||
fetchComposeSuggestions,
|
fetchComposeSuggestions,
|
||||||
insertEmojiCompose,
|
insertEmojiCompose,
|
||||||
|
@ -57,6 +58,7 @@ function mapStateToProps (state) {
|
||||||
media: state.getIn(['compose', 'media_attachments']),
|
media: state.getIn(['compose', 'media_attachments']),
|
||||||
preselectDate: state.getIn(['compose', 'preselectDate']),
|
preselectDate: state.getIn(['compose', 'preselectDate']),
|
||||||
privacy: state.getIn(['compose', 'privacy']),
|
privacy: state.getIn(['compose', 'privacy']),
|
||||||
|
contentType: state.getIn(['compose', 'content_type']),
|
||||||
sideArm: sideArmPrivacy,
|
sideArm: sideArmPrivacy,
|
||||||
sensitive: state.getIn(['compose', 'sensitive']),
|
sensitive: state.getIn(['compose', 'sensitive']),
|
||||||
showSearch: state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']),
|
showSearch: state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']),
|
||||||
|
@ -98,6 +100,10 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
dispatch(changeComposeSpoilerText(text));
|
dispatch(changeComposeSpoilerText(text));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
onChangeContentType(value) {
|
||||||
|
dispatch(changeComposeContentType(value));
|
||||||
|
},
|
||||||
|
|
||||||
onPaste(files) {
|
onPaste(files) {
|
||||||
dispatch(uploadCompose(files));
|
dispatch(uploadCompose(files));
|
||||||
},
|
},
|
||||||
|
|
|
@ -29,7 +29,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps, mapDispatchToProps)
|
export default @connect(mapStateToProps)
|
||||||
@injectIntl
|
@injectIntl
|
||||||
class Compose extends React.PureComponent {
|
class Compose extends React.PureComponent {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
|
|
|
@ -25,6 +25,7 @@ import {
|
||||||
COMPOSE_SPOILERNESS_CHANGE,
|
COMPOSE_SPOILERNESS_CHANGE,
|
||||||
COMPOSE_SPOILER_TEXT_CHANGE,
|
COMPOSE_SPOILER_TEXT_CHANGE,
|
||||||
COMPOSE_VISIBILITY_CHANGE,
|
COMPOSE_VISIBILITY_CHANGE,
|
||||||
|
COMPOSE_CONTENT_TYPE_CHANGE,
|
||||||
COMPOSE_EMOJI_INSERT,
|
COMPOSE_EMOJI_INSERT,
|
||||||
COMPOSE_UPLOAD_CHANGE_REQUEST,
|
COMPOSE_UPLOAD_CHANGE_REQUEST,
|
||||||
COMPOSE_UPLOAD_CHANGE_SUCCESS,
|
COMPOSE_UPLOAD_CHANGE_SUCCESS,
|
||||||
|
@ -66,6 +67,7 @@ const initialState = ImmutableMap({
|
||||||
spoiler: false,
|
spoiler: false,
|
||||||
spoiler_text: '',
|
spoiler_text: '',
|
||||||
privacy: null,
|
privacy: null,
|
||||||
|
content_type: 'text/plain',
|
||||||
text: '',
|
text: '',
|
||||||
focusDate: null,
|
focusDate: null,
|
||||||
caretPosition: null,
|
caretPosition: null,
|
||||||
|
@ -310,6 +312,10 @@ export default function compose(state = initialState, action) {
|
||||||
return state
|
return state
|
||||||
.set('privacy', action.value)
|
.set('privacy', action.value)
|
||||||
.set('idempotencyKey', uuid());
|
.set('idempotencyKey', uuid());
|
||||||
|
case COMPOSE_CONTENT_TYPE_CHANGE:
|
||||||
|
return state
|
||||||
|
.set('content_type', action.value)
|
||||||
|
.set('idempotencyKey', uuid());
|
||||||
case COMPOSE_CHANGE:
|
case COMPOSE_CHANGE:
|
||||||
return state
|
return state
|
||||||
.set('text', action.text)
|
.set('text', action.text)
|
||||||
|
|
Loading…
Reference in New Issue