From e4bc013d6f5e0fb8c6e612460182207a6c5d1c43 Mon Sep 17 00:00:00 2001 From: kibigo! Date: Fri, 5 Jan 2018 18:23:06 -0800 Subject: Threaded mode~ --- app/javascript/flavours/glitch/actions/compose.js | 12 +++- .../flavours/glitch/features/composer/index.js | 21 +++---- .../glitch/features/composer/options/index.js | 63 +++++++++++++-------- .../glitch/features/composer/textarea/index.js | 7 +++ app/javascript/flavours/glitch/locales/en.js | 8 ++- app/javascript/flavours/glitch/locales/ja.js | 4 +- app/javascript/flavours/glitch/reducers/compose.js | 64 +++++++++++++++++++--- .../glitch/styles/components/composer.scss | 21 +++++++ app/javascript/flavours/glitch/util/js_helpers.js | 5 ++ 9 files changed, 157 insertions(+), 48 deletions(-) create mode 100644 app/javascript/flavours/glitch/util/js_helpers.js (limited to 'app/javascript') diff --git a/app/javascript/flavours/glitch/actions/compose.js b/app/javascript/flavours/glitch/actions/compose.js index 31866d223..a88dba1b1 100644 --- a/app/javascript/flavours/glitch/actions/compose.js +++ b/app/javascript/flavours/glitch/actions/compose.js @@ -61,7 +61,7 @@ export function replyCompose(status, router) { status: status, }); - if (!getState().getIn(['compose', 'mounted'])) { + if (router && !getState().getIn(['compose', 'mounted'])) { router.push('/statuses/new'); } }; @@ -118,6 +118,11 @@ export function submitCompose() { }).then(function (response) { dispatch(submitComposeSuccess({ ...response.data })); + // If the response has no data then we can't do anything else. + if (!response.data) { + return; + } + // To make the app more responsive, immediately get the status into the columns const insertOrRefresh = (timelineId, refreshAction) => { @@ -341,10 +346,11 @@ export function unmountCompose() { }; }; -export function toggleComposeAdvancedOption(option) { +export function changeComposeAdvancedOption(option, value) { return { + option, type: COMPOSE_ADVANCED_OPTIONS_CHANGE, - option: option, + value, }; } diff --git a/app/javascript/flavours/glitch/features/composer/index.js b/app/javascript/flavours/glitch/features/composer/index.js index 3582dedfe..cae9bf9f2 100644 --- a/app/javascript/flavours/glitch/features/composer/index.js +++ b/app/javascript/flavours/glitch/features/composer/index.js @@ -7,6 +7,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import { cancelReplyCompose, changeCompose, + changeComposeAdvancedOption, changeComposeSensitivity, changeComposeSpoilerText, changeComposeSpoilerness, @@ -18,7 +19,6 @@ import { mountCompose, selectComposeSuggestion, submitCompose, - toggleComposeAdvancedOption, undoUploadCompose, unmountCompose, uploadCompose, @@ -49,8 +49,8 @@ function mapStateToProps (state) { const inReplyTo = state.getIn(['compose', 'in_reply_to']); return { acceptContentTypes: state.getIn(['media_attachments', 'accept_content_types']).toArray().join(','), + advancedOptions: state.getIn(['compose', 'advanced_options']), amUnlocked: !state.getIn(['accounts', me, 'locked']), - doNotFederate: state.getIn(['compose', 'advanced_options', 'do_not_federate']), focusDate: state.getIn(['compose', 'focusDate']), isSubmitting: state.getIn(['compose', 'is_submitting']), isUploading: state.getIn(['compose', 'is_uploading']), @@ -76,6 +76,7 @@ function mapStateToProps (state) { // Dispatch mapping. const mapDispatchToProps = { onCancelReply: cancelReplyCompose, + onChangeAdvancedOption: changeComposeAdvancedOption, onChangeDescription: changeUploadCompose, onChangeSensitivity: changeComposeSensitivity, onChangeSpoilerText: changeComposeSpoilerText, @@ -91,7 +92,6 @@ const mapDispatchToProps = { onOpenDoodleModal: openModal.bind(null, 'DOODLE', { noEsc: true }), onSelectSuggestion: selectComposeSuggestion, onSubmit: submitCompose, - onToggleAdvancedOption: toggleComposeAdvancedOption, onUndoUpload: undoUploadCompose, onUnmount: unmountCompose, onUpload: uploadCompose, @@ -267,14 +267,15 @@ class Composer extends React.Component { } = this.handlers; const { acceptContentTypes, + advancedOptions, amUnlocked, - doNotFederate, intl, isSubmitting, isUploading, layout, media, onCancelReply, + onChangeAdvancedOption, onChangeDescription, onChangeSensitivity, onChangeSpoilerness, @@ -285,7 +286,6 @@ class Composer extends React.Component { onFetchSuggestions, onOpenActionsModal, onOpenDoodleModal, - onToggleAdvancedOption, onUndoUpload, onUpload, privacy, @@ -321,6 +321,7 @@ class Composer extends React.Component { /> ) : null} = 4 || media.some( item => item.get('type') === 'video' )} hasMedia={!!media.size} intl={intl} + onChangeAdvancedOption={onChangeAdvancedOption} onChangeSensitivity={onChangeSensitivity} onChangeVisibility={onChangeVisibility} onDoodleOpen={onOpenDoodleModal} onModalClose={onCloseModal} onModalOpen={onOpenActionsModal} - onToggleAdvancedOption={onToggleAdvancedOption} onToggleSpoiler={onChangeSpoilerness} onUpload={onUpload} privacy={privacy} @@ -368,7 +369,7 @@ class Composer extends React.Component { spoiler={spoiler} /> - , - name: 'do_not_federate', - on: doNotFederate, - text: , - }, - ]} - onChange={onToggleAdvancedOption} - onModalClose={onModalClose} - onModalOpen={onModalOpen} - title={intl.formatMessage(messages.advanced_options_icon_title)} - /> + {advancedOptions ? ( + !!value)} + disabled={disabled} + icon='ellipsis-h' + items={[ + { + meta: , + name: 'do_not_federate', + on: advancedOptions.get('do_not_federate'), + text: , + }, + { + meta: , + name: 'threaded_mode', + on: advancedOptions.get('threaded_mode'), + text: , + }, + ]} + onChange={onChangeAdvancedOption} + onModalClose={onModalClose} + onModalOpen={onModalOpen} + title={intl.formatMessage(messages.advanced_options_icon_title)} + /> + ) : null} ); } @@ -309,17 +326,17 @@ export default class ComposerOptions extends React.PureComponent { // Props. ComposerOptions.propTypes = { acceptContentTypes: PropTypes.string, + advancedOptions: ImmutablePropTypes.map, disabled: PropTypes.bool, - doNotFederate: PropTypes.bool, full: PropTypes.bool, hasMedia: PropTypes.bool, intl: PropTypes.object.isRequired, + onChangeAdvancedOption: PropTypes.func, onChangeSensitivity: PropTypes.func, onChangeVisibility: PropTypes.func, onDoodleOpen: PropTypes.func, onModalClose: PropTypes.func, onModalOpen: PropTypes.func, - onToggleAdvancedOption: PropTypes.func, onToggleSpoiler: PropTypes.func, onUpload: PropTypes.func, privacy: PropTypes.string, diff --git a/app/javascript/flavours/glitch/features/composer/textarea/index.js b/app/javascript/flavours/glitch/features/composer/textarea/index.js index 2e0b3e3d7..0f5fd4d4d 100644 --- a/app/javascript/flavours/glitch/features/composer/textarea/index.js +++ b/app/javascript/flavours/glitch/features/composer/textarea/index.js @@ -10,6 +10,7 @@ import Textarea from 'react-textarea-autosize'; // Components. import EmojiPicker from 'flavours/glitch/features/emoji_picker'; +import ComposerTextareaIcons from './icons'; import ComposerTextareaSuggestions from './suggestions'; // Utils. @@ -232,6 +233,7 @@ export default class ComposerTextarea extends React.Component { handleRefTextarea, } = this.handlers; const { + advancedOptions, autoFocus, disabled, intl, @@ -249,6 +251,10 @@ export default class ComposerTextarea extends React.Component {