diff --git a/app/javascript/flavours/glitch/features/composer/index.js b/app/javascript/flavours/glitch/features/composer/index.js index de85340a3..21b03be39 100644 --- a/app/javascript/flavours/glitch/features/composer/index.js +++ b/app/javascript/flavours/glitch/features/composer/index.js @@ -56,6 +56,7 @@ function mapStateToProps (state) { advancedOptions: state.getIn(['compose', 'advanced_options']), amUnlocked: !state.getIn(['accounts', me, 'locked']), focusDate: state.getIn(['compose', 'focusDate']), + caretPosition: state.getIn(['compose', 'caretPosition']), isSubmitting: state.getIn(['compose', 'is_submitting']), isUploading: state.getIn(['compose', 'is_uploading']), layout: state.getIn(['local_settings', 'layout']), @@ -117,7 +118,6 @@ const handlers = { handleEmoji (data) { const { textarea: { selectionStart } } = this; const { onInsertEmoji } = this.props; - this.caretPos = selectionStart + data.native.length + 1; if (onInsertEmoji) { onInsertEmoji(selectionStart, data); } @@ -139,7 +139,6 @@ const handlers = { // Selects a suggestion from the autofill. handleSelect (tokenStart, token, value) { const { onSelectSuggestion } = this.props; - this.caretPos = null; if (onSelectSuggestion) { onSelectSuggestion(tokenStart, token, value); } @@ -191,20 +190,9 @@ class Composer extends React.Component { assignHandlers(this, handlers); // Instance variables. - this.caretPos = null; this.textarea = null; } - // If this is the update where we've finished uploading, - // save the last caret position so we can restore it below! - componentWillReceiveProps (nextProps) { - const { textarea } = this; - const { isUploading } = this.props; - if (textarea && isUploading && !nextProps.isUploading) { - this.caretPos = textarea.selectionStart; - } - } - // Tells our state the composer has been mounted. componentDidMount () { const { onMount } = this.props; @@ -228,17 +216,13 @@ class Composer extends React.Component { // - Replying to more than one user, selects any usernames past // the first; this provides a convenient shortcut to drop // everyone else from the conversation. - // - If we've just finished uploading an image, and have a saved - // caret position, restores the cursor to that position after the - // text changes. componentDidUpdate (prevProps) { const { - caretPos, textarea, } = this; const { focusDate, - isUploading, + caretPosition, isSubmitting, preselectDate, text, @@ -246,14 +230,14 @@ class Composer extends React.Component { let selectionEnd, selectionStart; // Caret/selection handling. - if (focusDate !== prevProps.focusDate || (prevProps.isUploading && !isUploading && !isNaN(caretPos) && caretPos !== null)) { + if (focusDate !== prevProps.focusDate) { switch (true) { case preselectDate !== prevProps.preselectDate: selectionStart = text.search(/\s/) + 1; selectionEnd = text.length; break; - case !isNaN(caretPos) && caretPos !== null: - selectionStart = selectionEnd = caretPos; + case !isNaN(caretPosition) && caretPosition !== null: + selectionStart = selectionEnd = caretPosition; break; default: selectionStart = selectionEnd = text.length; @@ -410,6 +394,7 @@ Composer.propTypes = { advancedOptions: ImmutablePropTypes.map, amUnlocked: PropTypes.bool, focusDate: PropTypes.instanceOf(Date), + caretPosition: PropTypes.number, isSubmitting: PropTypes.bool, isUploading: PropTypes.bool, layout: PropTypes.string, diff --git a/app/javascript/flavours/glitch/reducers/compose.js b/app/javascript/flavours/glitch/reducers/compose.js index f79fa63d2..24a8af86f 100644 --- a/app/javascript/flavours/glitch/reducers/compose.js +++ b/app/javascript/flavours/glitch/reducers/compose.js @@ -56,6 +56,7 @@ const initialState = ImmutableMap({ privacy: null, text: '', focusDate: null, + caretPosition: null, preselectDate: null, in_reply_to: null, is_submitting: false, @@ -148,6 +149,7 @@ function continueThread (state, status) { map.update('media_attachments', list => list.clear()); map.set('idempotencyKey', uuid()); map.set('focusDate', new Date()); + map.set('caretPosition', null); map.set('preselectDate', new Date()); }); } @@ -159,7 +161,6 @@ function appendMedia(state, media) { map.update('media_attachments', list => list.push(media)); map.set('is_uploading', false); map.set('resetFileKey', Math.floor((Math.random() * 0x10000))); - map.set('focusDate', new Date()); map.set('idempotencyKey', uuid()); if (prevSize === 0 && (state.get('default_sensitive') || state.get('spoiler'))) { @@ -187,6 +188,7 @@ const insertSuggestion = (state, position, token, completion) => { map.set('suggestion_token', null); map.update('suggestions', ImmutableList(), list => list.clear()); map.set('focusDate', new Date()); + map.set('caretPosition', position + completion.length + 1); map.set('idempotencyKey', uuid()); }); }; @@ -197,6 +199,7 @@ const insertEmoji = (state, position, emojiData) => { return state.withMutations(map => { map.update('text', oldText => `${oldText.slice(0, position)}${emoji}\u200B${oldText.slice(position)}`); map.set('focusDate', new Date()); + map.set('caretPosition', position + emoji.length + 1); map.set('idempotencyKey', uuid()); }); }; @@ -278,6 +281,7 @@ export default function compose(state = initialState, action) { map => map.merge(new ImmutableMap({ do_not_federate: /👁\ufe0f?\u200b?(?:<\/p>)?$/.test(action.status.get('content')) })) ); map.set('focusDate', new Date()); + map.set('caretPosition', null); map.set('preselectDate', new Date()); map.set('idempotencyKey', uuid()); @@ -325,6 +329,7 @@ export default function compose(state = initialState, action) { return state.withMutations(map => { map.update('text', text => [text.trim(), `@${action.account.get('acct')} `].filter((str) => str.length !== 0).join(' ')); map.set('focusDate', new Date()); + map.set('caretPosition', null); map.set('idempotencyKey', uuid()); }); case COMPOSE_DIRECT: @@ -332,6 +337,7 @@ export default function compose(state = initialState, action) { map.update('text', text => [text.trim(), `@${action.account.get('acct')} `].filter((str) => str.length !== 0).join(' ')); map.set('privacy', 'direct'); map.set('focusDate', new Date()); + map.set('caretPosition', null); map.set('idempotencyKey', uuid()); }); case COMPOSE_SUGGESTIONS_CLEAR: