mirror of
https://github.com/element-hq/element-web
synced 2024-11-28 12:28:50 +03:00
Merge pull request #3392 from matrix-org/bwindels/cider-paste-plain
New composer: fix pasting from word processors
This commit is contained in:
commit
df4762871a
3 changed files with 32 additions and 5 deletions
|
@ -25,10 +25,12 @@ import {
|
||||||
formatRangeAsQuote,
|
formatRangeAsQuote,
|
||||||
formatRangeAsCode,
|
formatRangeAsCode,
|
||||||
formatInline,
|
formatInline,
|
||||||
|
replaceRangeAndMoveCaret,
|
||||||
} from '../../../editor/operations';
|
} from '../../../editor/operations';
|
||||||
import {getCaretOffsetAndText, getRangeForSelection} from '../../../editor/dom';
|
import {getCaretOffsetAndText, getRangeForSelection} from '../../../editor/dom';
|
||||||
import Autocomplete from '../rooms/Autocomplete';
|
import Autocomplete from '../rooms/Autocomplete';
|
||||||
import {autoCompleteCreator} from '../../../editor/parts';
|
import {autoCompleteCreator} from '../../../editor/parts';
|
||||||
|
import {parsePlainTextMessage} from '../../../editor/deserialize';
|
||||||
import {renderModel} from '../../../editor/render';
|
import {renderModel} from '../../../editor/render';
|
||||||
import {Room} from 'matrix-js-sdk';
|
import {Room} from 'matrix-js-sdk';
|
||||||
import TypingStore from "../../../stores/TypingStore";
|
import TypingStore from "../../../stores/TypingStore";
|
||||||
|
@ -172,6 +174,18 @@ export default class BasicMessageEditor extends React.Component {
|
||||||
this._onInput({inputType: "insertCompositionText"});
|
this._onInput({inputType: "insertCompositionText"});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onPaste = (event) => {
|
||||||
|
const {model} = this.props;
|
||||||
|
const {partCreator} = model;
|
||||||
|
const text = event.clipboardData.getData("text/plain");
|
||||||
|
if (text) {
|
||||||
|
const range = getRangeForSelection(this._editorRef, model, document.getSelection());
|
||||||
|
const parts = parsePlainTextMessage(text, partCreator);
|
||||||
|
replaceRangeAndMoveCaret(range, parts);
|
||||||
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_onInput = (event) => {
|
_onInput = (event) => {
|
||||||
// ignore any input while doing IME compositions
|
// ignore any input while doing IME compositions
|
||||||
if (this._isIMEComposing) {
|
if (this._isIMEComposing) {
|
||||||
|
@ -495,6 +509,7 @@ export default class BasicMessageEditor extends React.Component {
|
||||||
tabIndex="1"
|
tabIndex="1"
|
||||||
onBlur={this._onBlur}
|
onBlur={this._onBlur}
|
||||||
onFocus={this._onFocus}
|
onFocus={this._onFocus}
|
||||||
|
onPaste={this._onPaste}
|
||||||
onKeyDown={this._onKeyDown}
|
onKeyDown={this._onKeyDown}
|
||||||
ref={ref => this._editorRef = ref}
|
ref={ref => this._editorRef = ref}
|
||||||
aria-label={this.props.label}
|
aria-label={this.props.label}
|
||||||
|
|
|
@ -232,7 +232,7 @@ function parseHtmlMessage(html, partCreator, isQuotedMessage) {
|
||||||
return parts;
|
return parts;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parsePlainTextMessage(body, partCreator, isQuotedMessage) {
|
export function parsePlainTextMessage(body, partCreator, isQuotedMessage) {
|
||||||
const lines = body.split("\n");
|
const lines = body.split("\n");
|
||||||
const parts = lines.reduce((parts, line, i) => {
|
const parts = lines.reduce((parts, line, i) => {
|
||||||
if (isQuotedMessage) {
|
if (isQuotedMessage) {
|
||||||
|
|
|
@ -18,7 +18,8 @@ limitations under the License.
|
||||||
* Some common queries and transformations on the editor model
|
* Some common queries and transformations on the editor model
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export function replaceRangeAndExpandSelection(model, range, newParts) {
|
export function replaceRangeAndExpandSelection(range, newParts) {
|
||||||
|
const {model} = range;
|
||||||
model.transform(() => {
|
model.transform(() => {
|
||||||
const oldLen = range.length;
|
const oldLen = range.length;
|
||||||
const addedLen = range.replace(newParts);
|
const addedLen = range.replace(newParts);
|
||||||
|
@ -28,6 +29,17 @@ export function replaceRangeAndExpandSelection(model, range, newParts) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function replaceRangeAndMoveCaret(range, newParts) {
|
||||||
|
const {model} = range;
|
||||||
|
model.transform(() => {
|
||||||
|
const oldLen = range.length;
|
||||||
|
const addedLen = range.replace(newParts);
|
||||||
|
const firstOffset = range.start.asOffset(model);
|
||||||
|
const lastOffset = firstOffset.add(oldLen + addedLen);
|
||||||
|
return lastOffset.asPosition(model);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function rangeStartsAtBeginningOfLine(range) {
|
export function rangeStartsAtBeginningOfLine(range) {
|
||||||
const {model} = range;
|
const {model} = range;
|
||||||
const startsWithPartial = range.start.offset !== 0;
|
const startsWithPartial = range.start.offset !== 0;
|
||||||
|
@ -63,7 +75,7 @@ export function formatRangeAsQuote(range) {
|
||||||
}
|
}
|
||||||
|
|
||||||
parts.push(partCreator.newline());
|
parts.push(partCreator.newline());
|
||||||
replaceRangeAndExpandSelection(model, range, parts);
|
replaceRangeAndExpandSelection(range, parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatRangeAsCode(range) {
|
export function formatRangeAsCode(range) {
|
||||||
|
@ -85,7 +97,7 @@ export function formatRangeAsCode(range) {
|
||||||
parts.unshift(partCreator.plain("`"));
|
parts.unshift(partCreator.plain("`"));
|
||||||
parts.push(partCreator.plain("`"));
|
parts.push(partCreator.plain("`"));
|
||||||
}
|
}
|
||||||
replaceRangeAndExpandSelection(model, range, parts);
|
replaceRangeAndExpandSelection(range, parts);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatInline(range, prefix, suffix = prefix) {
|
export function formatInline(range, prefix, suffix = prefix) {
|
||||||
|
@ -93,5 +105,5 @@ export function formatInline(range, prefix, suffix = prefix) {
|
||||||
const {partCreator} = model;
|
const {partCreator} = model;
|
||||||
parts.unshift(partCreator.plain(prefix));
|
parts.unshift(partCreator.plain(prefix));
|
||||||
parts.push(partCreator.plain(suffix));
|
parts.push(partCreator.plain(suffix));
|
||||||
replaceRangeAndExpandSelection(model, range, parts);
|
replaceRangeAndExpandSelection(range, parts);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue