mirror of
https://github.com/mastodon/mastodon.git
synced 2024-11-15 03:15:32 +00:00
Merge pull request #508 from ThibG/glitch-soc/fixes/remove-leftover-from-attachment-url-insertion
Fix caret position after inserting suggestions
This commit is contained in:
commit
22bc07998c
|
@ -56,6 +56,7 @@ function mapStateToProps (state) {
|
||||||
advancedOptions: state.getIn(['compose', 'advanced_options']),
|
advancedOptions: state.getIn(['compose', 'advanced_options']),
|
||||||
amUnlocked: !state.getIn(['accounts', me, 'locked']),
|
amUnlocked: !state.getIn(['accounts', me, 'locked']),
|
||||||
focusDate: state.getIn(['compose', 'focusDate']),
|
focusDate: state.getIn(['compose', 'focusDate']),
|
||||||
|
caretPosition: state.getIn(['compose', 'caretPosition']),
|
||||||
isSubmitting: state.getIn(['compose', 'is_submitting']),
|
isSubmitting: state.getIn(['compose', 'is_submitting']),
|
||||||
isUploading: state.getIn(['compose', 'is_uploading']),
|
isUploading: state.getIn(['compose', 'is_uploading']),
|
||||||
layout: state.getIn(['local_settings', 'layout']),
|
layout: state.getIn(['local_settings', 'layout']),
|
||||||
|
@ -117,7 +118,6 @@ const handlers = {
|
||||||
handleEmoji (data) {
|
handleEmoji (data) {
|
||||||
const { textarea: { selectionStart } } = this;
|
const { textarea: { selectionStart } } = this;
|
||||||
const { onInsertEmoji } = this.props;
|
const { onInsertEmoji } = this.props;
|
||||||
this.caretPos = selectionStart + data.native.length + 1;
|
|
||||||
if (onInsertEmoji) {
|
if (onInsertEmoji) {
|
||||||
onInsertEmoji(selectionStart, data);
|
onInsertEmoji(selectionStart, data);
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,6 @@ const handlers = {
|
||||||
// Selects a suggestion from the autofill.
|
// Selects a suggestion from the autofill.
|
||||||
handleSelect (tokenStart, token, value) {
|
handleSelect (tokenStart, token, value) {
|
||||||
const { onSelectSuggestion } = this.props;
|
const { onSelectSuggestion } = this.props;
|
||||||
this.caretPos = null;
|
|
||||||
if (onSelectSuggestion) {
|
if (onSelectSuggestion) {
|
||||||
onSelectSuggestion(tokenStart, token, value);
|
onSelectSuggestion(tokenStart, token, value);
|
||||||
}
|
}
|
||||||
|
@ -191,20 +190,9 @@ class Composer extends React.Component {
|
||||||
assignHandlers(this, handlers);
|
assignHandlers(this, handlers);
|
||||||
|
|
||||||
// Instance variables.
|
// Instance variables.
|
||||||
this.caretPos = null;
|
|
||||||
this.textarea = 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.
|
// Tells our state the composer has been mounted.
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const { onMount } = this.props;
|
const { onMount } = this.props;
|
||||||
|
@ -228,17 +216,13 @@ class Composer extends React.Component {
|
||||||
// - Replying to more than one user, selects any usernames past
|
// - Replying to more than one user, selects any usernames past
|
||||||
// the first; this provides a convenient shortcut to drop
|
// the first; this provides a convenient shortcut to drop
|
||||||
// everyone else from the conversation.
|
// 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) {
|
componentDidUpdate (prevProps) {
|
||||||
const {
|
const {
|
||||||
caretPos,
|
|
||||||
textarea,
|
textarea,
|
||||||
} = this;
|
} = this;
|
||||||
const {
|
const {
|
||||||
focusDate,
|
focusDate,
|
||||||
isUploading,
|
caretPosition,
|
||||||
isSubmitting,
|
isSubmitting,
|
||||||
preselectDate,
|
preselectDate,
|
||||||
text,
|
text,
|
||||||
|
@ -246,14 +230,14 @@ class Composer extends React.Component {
|
||||||
let selectionEnd, selectionStart;
|
let selectionEnd, selectionStart;
|
||||||
|
|
||||||
// Caret/selection handling.
|
// Caret/selection handling.
|
||||||
if (focusDate !== prevProps.focusDate || (prevProps.isUploading && !isUploading && !isNaN(caretPos) && caretPos !== null)) {
|
if (focusDate !== prevProps.focusDate) {
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case preselectDate !== prevProps.preselectDate:
|
case preselectDate !== prevProps.preselectDate:
|
||||||
selectionStart = text.search(/\s/) + 1;
|
selectionStart = text.search(/\s/) + 1;
|
||||||
selectionEnd = text.length;
|
selectionEnd = text.length;
|
||||||
break;
|
break;
|
||||||
case !isNaN(caretPos) && caretPos !== null:
|
case !isNaN(caretPosition) && caretPosition !== null:
|
||||||
selectionStart = selectionEnd = caretPos;
|
selectionStart = selectionEnd = caretPosition;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
selectionStart = selectionEnd = text.length;
|
selectionStart = selectionEnd = text.length;
|
||||||
|
@ -410,6 +394,7 @@ Composer.propTypes = {
|
||||||
advancedOptions: ImmutablePropTypes.map,
|
advancedOptions: ImmutablePropTypes.map,
|
||||||
amUnlocked: PropTypes.bool,
|
amUnlocked: PropTypes.bool,
|
||||||
focusDate: PropTypes.instanceOf(Date),
|
focusDate: PropTypes.instanceOf(Date),
|
||||||
|
caretPosition: PropTypes.number,
|
||||||
isSubmitting: PropTypes.bool,
|
isSubmitting: PropTypes.bool,
|
||||||
isUploading: PropTypes.bool,
|
isUploading: PropTypes.bool,
|
||||||
layout: PropTypes.string,
|
layout: PropTypes.string,
|
||||||
|
|
|
@ -56,6 +56,7 @@ const initialState = ImmutableMap({
|
||||||
privacy: null,
|
privacy: null,
|
||||||
text: '',
|
text: '',
|
||||||
focusDate: null,
|
focusDate: null,
|
||||||
|
caretPosition: null,
|
||||||
preselectDate: null,
|
preselectDate: null,
|
||||||
in_reply_to: null,
|
in_reply_to: null,
|
||||||
is_submitting: false,
|
is_submitting: false,
|
||||||
|
@ -148,6 +149,7 @@ function continueThread (state, status) {
|
||||||
map.update('media_attachments', list => list.clear());
|
map.update('media_attachments', list => list.clear());
|
||||||
map.set('idempotencyKey', uuid());
|
map.set('idempotencyKey', uuid());
|
||||||
map.set('focusDate', new Date());
|
map.set('focusDate', new Date());
|
||||||
|
map.set('caretPosition', null);
|
||||||
map.set('preselectDate', new Date());
|
map.set('preselectDate', new Date());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -159,7 +161,6 @@ function appendMedia(state, media) {
|
||||||
map.update('media_attachments', list => list.push(media));
|
map.update('media_attachments', list => list.push(media));
|
||||||
map.set('is_uploading', false);
|
map.set('is_uploading', false);
|
||||||
map.set('resetFileKey', Math.floor((Math.random() * 0x10000)));
|
map.set('resetFileKey', Math.floor((Math.random() * 0x10000)));
|
||||||
map.set('focusDate', new Date());
|
|
||||||
map.set('idempotencyKey', uuid());
|
map.set('idempotencyKey', uuid());
|
||||||
|
|
||||||
if (prevSize === 0 && (state.get('default_sensitive') || state.get('spoiler'))) {
|
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.set('suggestion_token', null);
|
||||||
map.update('suggestions', ImmutableList(), list => list.clear());
|
map.update('suggestions', ImmutableList(), list => list.clear());
|
||||||
map.set('focusDate', new Date());
|
map.set('focusDate', new Date());
|
||||||
|
map.set('caretPosition', position + completion.length + 1);
|
||||||
map.set('idempotencyKey', uuid());
|
map.set('idempotencyKey', uuid());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -197,6 +199,7 @@ const insertEmoji = (state, position, emojiData) => {
|
||||||
return state.withMutations(map => {
|
return state.withMutations(map => {
|
||||||
map.update('text', oldText => `${oldText.slice(0, position)}${emoji}\u200B${oldText.slice(position)}`);
|
map.update('text', oldText => `${oldText.slice(0, position)}${emoji}\u200B${oldText.slice(position)}`);
|
||||||
map.set('focusDate', new Date());
|
map.set('focusDate', new Date());
|
||||||
|
map.set('caretPosition', position + emoji.length + 1);
|
||||||
map.set('idempotencyKey', uuid());
|
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 => map.merge(new ImmutableMap({ do_not_federate: /👁\ufe0f?\u200b?(?:<\/p>)?$/.test(action.status.get('content')) }))
|
||||||
);
|
);
|
||||||
map.set('focusDate', new Date());
|
map.set('focusDate', new Date());
|
||||||
|
map.set('caretPosition', null);
|
||||||
map.set('preselectDate', new Date());
|
map.set('preselectDate', new Date());
|
||||||
map.set('idempotencyKey', uuid());
|
map.set('idempotencyKey', uuid());
|
||||||
|
|
||||||
|
@ -325,6 +329,7 @@ export default function compose(state = initialState, action) {
|
||||||
return state.withMutations(map => {
|
return state.withMutations(map => {
|
||||||
map.update('text', text => [text.trim(), `@${action.account.get('acct')} `].filter((str) => str.length !== 0).join(' '));
|
map.update('text', text => [text.trim(), `@${action.account.get('acct')} `].filter((str) => str.length !== 0).join(' '));
|
||||||
map.set('focusDate', new Date());
|
map.set('focusDate', new Date());
|
||||||
|
map.set('caretPosition', null);
|
||||||
map.set('idempotencyKey', uuid());
|
map.set('idempotencyKey', uuid());
|
||||||
});
|
});
|
||||||
case COMPOSE_DIRECT:
|
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.update('text', text => [text.trim(), `@${action.account.get('acct')} `].filter((str) => str.length !== 0).join(' '));
|
||||||
map.set('privacy', 'direct');
|
map.set('privacy', 'direct');
|
||||||
map.set('focusDate', new Date());
|
map.set('focusDate', new Date());
|
||||||
|
map.set('caretPosition', null);
|
||||||
map.set('idempotencyKey', uuid());
|
map.set('idempotencyKey', uuid());
|
||||||
});
|
});
|
||||||
case COMPOSE_SUGGESTIONS_CLEAR:
|
case COMPOSE_SUGGESTIONS_CLEAR:
|
||||||
|
|
Loading…
Reference in a new issue