mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-12-28 11:24:11 +08:00
This commit is contained in:
parent
ed3f58d872
commit
6a758dc784
3 changed files with 89 additions and 9 deletions
|
@ -33,6 +33,10 @@
|
|||
-webkit-margin-end: initial !important;
|
||||
}
|
||||
|
||||
.RichEditor-root .link {
|
||||
color: @text-color-link;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.RichEditor-root .custom-block-selected,
|
||||
.RichEditor-root .uneditable.custom-block-selected {
|
||||
border: 1px dashed @text-color;
|
||||
|
@ -143,11 +147,15 @@
|
|||
flex: 1;
|
||||
flex-shrink: 0;
|
||||
max-width: 32px;
|
||||
text-align: center;
|
||||
|
||||
.dropdown {
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
button {
|
||||
max-width: 50px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Mark } from 'slate';
|
|||
import AutoReplace from 'slate-auto-replace';
|
||||
import { RegExpUtils } from 'mailspring-exports';
|
||||
|
||||
import { BuildMarkButtonWithValuePicker } from './toolbar-component-factories';
|
||||
import { BuildMarkButtonWithValuePicker, getMarkOfType } from './toolbar-component-factories';
|
||||
|
||||
export const LINK_TYPE = 'link';
|
||||
|
||||
|
@ -22,14 +22,28 @@ function onPaste(event, change, editor) {
|
|||
}
|
||||
}
|
||||
|
||||
function renderMark({ mark, children }) {
|
||||
if (mark.type === LINK_TYPE) {
|
||||
const href = mark.data.href || mark.data.get('href');
|
||||
function renderMark({ mark, children, targetIsHTML }) {
|
||||
if (mark.type !== LINK_TYPE) {
|
||||
return;
|
||||
}
|
||||
const href = mark.data.href || mark.data.get('href');
|
||||
if (targetIsHTML) {
|
||||
return (
|
||||
<a href={href} title={href}>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
const onClick = e => {
|
||||
if (e.ctrlKey || e.metaKey) {
|
||||
AppEnv.windowEventHandler.openLink({ href, metaKey: e.metaKey });
|
||||
}
|
||||
};
|
||||
return (
|
||||
<span className="link" title={href} onClick={onClick}>
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,12 +80,22 @@ export default [
|
|||
BuildMarkButtonWithValuePicker({
|
||||
type: LINK_TYPE,
|
||||
field: 'href',
|
||||
iconClassOn: 'fa fa-unlink',
|
||||
iconClassOn: 'fa fa-link',
|
||||
iconClassOff: 'fa fa-link',
|
||||
placeholder: 'http://',
|
||||
}),
|
||||
],
|
||||
onPaste,
|
||||
onKeyDown: function onKeyDown(event, change) {
|
||||
// ensure space and enter always terminate links
|
||||
if (!['Space', 'Enter', ' ', 'Return'].includes(event.key)) {
|
||||
return;
|
||||
}
|
||||
const mark = getMarkOfType(change.value, LINK_TYPE);
|
||||
if (mark) {
|
||||
change.removeMark(mark);
|
||||
}
|
||||
},
|
||||
renderMark,
|
||||
rules,
|
||||
commands: {
|
||||
|
|
|
@ -35,6 +35,33 @@ function removeMarksOfTypeInRange(change, range, type) {
|
|||
return change;
|
||||
}
|
||||
|
||||
export function expandSelectionToRangeOfMark(change, type) {
|
||||
const { selection, document } = change.value;
|
||||
const node = document.getNode(selection.anchorKey);
|
||||
let start = selection.anchorOffset;
|
||||
let end = selection.anchorOffset;
|
||||
|
||||
// expand backwards until the mark disappears
|
||||
while (start > 0 && node.getMarksAtIndex(start).find(m => m.type === type)) {
|
||||
start -= 1;
|
||||
}
|
||||
// expand forwards until the mark disappears
|
||||
while (end < node.text.length - 1 && node.getMarksAtIndex(end + 1).find(m => m.type === type)) {
|
||||
end += 1;
|
||||
}
|
||||
|
||||
// expand selection
|
||||
change.select({
|
||||
anchorKey: selection.anchorKey,
|
||||
anchorOffset: start,
|
||||
focusKey: selection.anchorKey,
|
||||
focusOffset: end,
|
||||
isFocused: true,
|
||||
isBackward: false,
|
||||
});
|
||||
return change;
|
||||
}
|
||||
|
||||
export function hasMark(value, type) {
|
||||
return !!getMarkOfType(value, type);
|
||||
}
|
||||
|
@ -107,7 +134,10 @@ export function BuildMarkButtonWithValuePicker(config) {
|
|||
const active = getMarkOfType(this.props.value, config.type);
|
||||
const fieldValue = (active && active.data.get(config.field)) || '';
|
||||
this.setState({ expanded: true, fieldValue: fieldValue }, () => {
|
||||
setTimeout(() => this._inputEl.focus(), 0);
|
||||
setTimeout(() => {
|
||||
this._inputEl.focus();
|
||||
this._inputEl.select();
|
||||
}, 0);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -117,6 +147,13 @@ export function BuildMarkButtonWithValuePicker(config) {
|
|||
// attach the URL value to the LINK that was created when we opened the link modal
|
||||
const { value, onChange } = this.props;
|
||||
const { fieldValue } = this.state;
|
||||
|
||||
if (fieldValue.trim() === '') {
|
||||
this.onRemove(e);
|
||||
this.setState({ expanded: false, fieldValue: '' });
|
||||
return;
|
||||
}
|
||||
|
||||
const newMark = Mark.create({
|
||||
type: config.type,
|
||||
data: {
|
||||
|
@ -124,7 +161,17 @@ export function BuildMarkButtonWithValuePicker(config) {
|
|||
},
|
||||
});
|
||||
|
||||
if (value.selection.isCollapsed) {
|
||||
const active = getMarkOfType(this.props.value, config.type);
|
||||
if (active) {
|
||||
// update the active mark
|
||||
const change = value.change();
|
||||
expandSelectionToRangeOfMark(change, config.type);
|
||||
removeMarksOfTypeInRange(change, value.selection, config.type)
|
||||
.addMark(newMark)
|
||||
.focus();
|
||||
onChange(change);
|
||||
} else if (value.selection.isCollapsed) {
|
||||
// apply new mark to new text
|
||||
onChange(
|
||||
value
|
||||
.change()
|
||||
|
@ -135,6 +182,7 @@ export function BuildMarkButtonWithValuePicker(config) {
|
|||
.focus()
|
||||
);
|
||||
} else {
|
||||
// apply new mark to selected text
|
||||
onChange(
|
||||
removeMarksOfTypeInRange(value.change(), value.selection, config.type)
|
||||
.addMark(newMark)
|
||||
|
@ -175,7 +223,7 @@ export function BuildMarkButtonWithValuePicker(config) {
|
|||
onBlur={this.onBlur}
|
||||
>
|
||||
{active ? (
|
||||
<button className="active" onMouseDown={this.onRemove}>
|
||||
<button className="active" onMouseDown={this.onPrompt}>
|
||||
<i className={config.iconClassOn} />
|
||||
</button>
|
||||
) : (
|
||||
|
@ -198,7 +246,7 @@ export function BuildMarkButtonWithValuePicker(config) {
|
|||
}
|
||||
}}
|
||||
/>
|
||||
<button onMouseDown={this.onConfirm}>Add</button>
|
||||
<button onMouseDown={this.onConfirm}>{active ? 'Save' : 'Add'}</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue