mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-02-28 18:14:08 +08:00
fix(mail-merge/preview): Don't unmount components when toggling preview
Summary: See edgehill revision: https://phab.nylas.com/D3160 - CustomContenteditableComponents.get now takes a single component to register as an overlaid component, and this component will be passed a prop `{isPreview: true}` when it is meant to be rendered as a preview. Update scheduler and mail-merge to use this new api. - This prevents the mail merge state from being incorrectly updated when we toggled preview mode -- previously, it believed that the tokens had been unmounted when toggling preview, so they were incorrectly removed from the mail merge state. - Additionally, makes sure that tokens are correctly added to the mail merge state whenever a token is rendered via componentDidMount -- previously, we only added the token to state when a token was dropped on the contenteditable, however, a token might be pasted or an anchor node might be added by any other means, in which case we want the mail merge state to reflect that. (Adds docs about this) Test Plan: Manual Reviewers: jackie, evan Reviewed By: jackie, evan Differential Revision: https://phab.nylas.com/D3161
This commit is contained in:
parent
3b365dd9b1
commit
b223a38b73
5 changed files with 36 additions and 27 deletions
|
@ -483,7 +483,7 @@ body.platform-win32 {
|
|||
img.n1-overlaid-component-anchor-container {
|
||||
border: 0;
|
||||
}
|
||||
.toggle-serialized {
|
||||
.toggle-preview {
|
||||
position: absolute;
|
||||
top: -17px;
|
||||
right: 0;
|
||||
|
|
|
@ -7,11 +7,11 @@ class CustomContenteditableComponents {
|
|||
return this._components[componentKey]
|
||||
}
|
||||
|
||||
register(componentKey, components = {}) {
|
||||
if (!components.main) {
|
||||
throw new Error("Must register a `main` component and optionally a `serialized` component.")
|
||||
register(componentKey, component) {
|
||||
if (!component) {
|
||||
throw new Error("Must register a component.")
|
||||
}
|
||||
this._components[componentKey] = components
|
||||
this._components[componentKey] = component
|
||||
}
|
||||
|
||||
unregister(componentKey) {
|
||||
|
|
|
@ -45,7 +45,9 @@ export default class OverlaidComponents extends React.Component {
|
|||
return {
|
||||
anchorId: overlayId,
|
||||
anchorTag:
|
||||
`<img class="${className}" src="${IMG_SRC}" data-overlay-id="${overlayId}" data-component-props="${propsStr}" data-component-key="${componentKey}" style="${style}">`,
|
||||
`<img class="${className}" src="${IMG_SRC}" data-overlay-id="${overlayId}" ` +
|
||||
`data-component-props="${propsStr}" data-component-key="${componentKey}" ` +
|
||||
`style="${style}">`,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +55,7 @@ export default class OverlaidComponents extends React.Component {
|
|||
super(props);
|
||||
this.state = {
|
||||
anchorRectIds: [],
|
||||
serialized: false,
|
||||
previewMode: false,
|
||||
}
|
||||
this._anchorData = {}
|
||||
this._overlayData = {}
|
||||
|
@ -162,12 +164,20 @@ export default class OverlaidComponents extends React.Component {
|
|||
return updatedRegistry
|
||||
}
|
||||
|
||||
_renderSerializeToggle() {
|
||||
_onTogglePreview = () => {
|
||||
this.setState({previewMode: !this.state.previewMode})
|
||||
}
|
||||
|
||||
_renderPreviewToggle() {
|
||||
let msg = "Preview as recipient";
|
||||
if (this.state.serialized) {
|
||||
if (this.state.previewMode) {
|
||||
msg = "Return to editor"
|
||||
}
|
||||
return <a className="toggle-serialized" onClick={() => { this.setState({serialized: !this.state.serialized}) }}>{msg}</a>
|
||||
return (
|
||||
<a className="toggle-preview" onClick={this._onTogglePreview} >
|
||||
{msg}
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
_renderOverlaidComponents() {
|
||||
|
@ -177,25 +187,22 @@ export default class OverlaidComponents extends React.Component {
|
|||
if (!data) { throw new Error("No mounted rect for #{id}") }
|
||||
|
||||
const style = {left: data.left, top: data.top, position: 'absolute'}
|
||||
const componentData = CustomContenteditableComponents.get(data.componentKey);
|
||||
const component = CustomContenteditableComponents.get(data.componentKey);
|
||||
|
||||
if (!componentData) {
|
||||
if (!component) {
|
||||
// It's possible that the plugin with that will register this
|
||||
// componentKey hasn't loaded yet. This is common in popout
|
||||
// composers where 3rd party plugins are loaded later.
|
||||
continue
|
||||
}
|
||||
|
||||
const component = this.state.serialized ? componentData.serialized : componentData.main;
|
||||
|
||||
if (!component) { throw new Error(`No registered component for ${data.componentKey}`) }
|
||||
|
||||
let props = JSON.parse(data.componentProps);
|
||||
|
||||
props = Object.assign({}, this.props.exposedProps, props);
|
||||
const props = Object.assign({},
|
||||
this.props.exposedProps,
|
||||
JSON.parse(data.componentProps),
|
||||
{isPreview: this.state.previewMode}
|
||||
);
|
||||
|
||||
const el = React.createElement(component, props)
|
||||
|
||||
const wrap = (
|
||||
<span
|
||||
key={id}
|
||||
|
@ -209,7 +216,7 @@ export default class OverlaidComponents extends React.Component {
|
|||
|
||||
els.push(wrap)
|
||||
}
|
||||
const toggle = (els.length > 0) ? this._renderSerializeToggle() : false
|
||||
const toggle = (els.length > 0) ? this._renderPreviewToggle() : false
|
||||
return (
|
||||
<div ref="overlaidComponents" className="overlaid-components">
|
||||
{toggle}
|
||||
|
|
|
@ -49,18 +49,20 @@ export default class OverlaidComposerExtension extends ComposerExtension {
|
|||
const matcher = self.overlayMatches(self._anchorExtractRe(), outDraft.body)
|
||||
|
||||
for (const match of matcher) {
|
||||
const componentData = CustomContenteditableComponents.get(match.dataComponentKey);
|
||||
if (!componentData || !componentData.serialized) {
|
||||
const component = CustomContenteditableComponents.get(match.dataComponentKey);
|
||||
if (!component) {
|
||||
continue
|
||||
}
|
||||
const component = componentData.serialized
|
||||
const props = Object.assign({draft}, match.dataComponentProps);
|
||||
const props = Object.assign({draft, isPreview: true}, match.dataComponentProps);
|
||||
const el = React.createElement(component, props);
|
||||
let html = ReactDOMServer.renderToStaticMarkup(el);
|
||||
|
||||
html = `<overlay data-overlay-id="${match.dataOverlayId}" data-component-props="${OverlaidComponents.propsToDOMAttr(match.dataComponentProps)}" data-component-key="${match.dataComponentKey}" data-style="${match.dataStyle}">${html}</overlay>`
|
||||
|
||||
outBody = outBody.replace(OverlaidComposerExtension._anchorReplacerRe(match.dataOverlayId), html)
|
||||
outBody = outBody.replace(
|
||||
OverlaidComposerExtension._anchorReplacerRe(match.dataOverlayId),
|
||||
html
|
||||
)
|
||||
}
|
||||
|
||||
outDraft.body = outBody;
|
||||
|
|
2
src/pro
2
src/pro
|
@ -1 +1 @@
|
|||
Subproject commit b58b059bde6e81a70170ff03288200c55615c162
|
||||
Subproject commit 33cacbd129e3db61fa8f6c748af3428314413876
|
Loading…
Reference in a new issue