Skip to content

Commit

Permalink
fix(ot): submit ops error
Browse files Browse the repository at this point in the history
- optimize placeholder display timing
- data-element=ui node is not correctly filtered when submitting ops in collaborative interaction
  • Loading branch information
yanmao committed Sep 26, 2021
1 parent 62cd18c commit 1098559
Show file tree
Hide file tree
Showing 10 changed files with 93 additions and 44 deletions.
10 changes: 9 additions & 1 deletion packages/engine/src/change/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class ChangeEvent implements ChangeEventInterface {
return;
}
if (!this.isCardInput(event)) {
console.log('compositionstart');
this.engine.ot.startMutationCache();
}
// 组合输入法缓存协同
Expand Down Expand Up @@ -95,6 +96,7 @@ class ChangeEvent implements ChangeEventInterface {
if (this.engine.readonly) {
return;
}
console.log('compositionend');
this.isComposing = false;
});
//对系统工具栏操作拦截,一般针对移动端的文本上下文工具栏
Expand Down Expand Up @@ -150,6 +152,7 @@ class ChangeEvent implements ChangeEventInterface {
const { inputType } = event;
// 在组合输入法未正常执行结束命令插入就先提交协同
if (this.isComposing && !inputType.includes('Composition')) {
console.log('beforeinput', inputType);
this.engine.ot.submitMutationCache();
}
const commandTypes = ['format', 'history'];
Expand All @@ -172,10 +175,15 @@ class ChangeEvent implements ChangeEventInterface {
if (this.isCardInput(e)) {
return;
}

if (this.engine.isEmpty()) {
this.engine.showPlaceholder();
} else {
this.engine.hidePlaceholder();
}
if (inputTimeout) clearTimeout(inputTimeout);
inputTimeout = setTimeout(() => {
if (!this.isComposing) {
console.log('input');
callback(e);
// 组合输入法结束后提交协同
this.engine.ot.submitMutationCache();
Expand Down
10 changes: 10 additions & 0 deletions packages/engine/src/change/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,10 @@ class ChangeModel implements ChangeInterface {
endNode.append('<br />');
}
}

if (startNode.isEditable() && startNode.children().length === 0) {
startNode.html('<p><br /></p>');
}
//在非折叠,或者当前range对象和selection中的对象不一致的时候重新设置range
if (
selection &&
Expand Down Expand Up @@ -1362,6 +1366,12 @@ class ChangeModel implements ChangeInterface {
}
// 先删除范围内的所有内容
safeRange.extractContents();
if (
safeRange.startNode.isEditable() &&
safeRange.startNode.children().length === 0
) {
safeRange.startNode.html('<p><br /></p>');
}
safeRange.collapse(true);
// 后续处理
const { startNode } = safeRange
Expand Down
4 changes: 2 additions & 2 deletions packages/engine/src/engine/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class Container {
showPlaceholder() {
const { placeholder } = this.options;
if (placeholder) {
if (this.#styleElement)
if (this.#styleElement && this.#styleElement.parentNode)
document.body.removeChild(this.#styleElement);
this.#styleElement = document.createElement('style');
//const left = this.node.css('padding-left');
Expand All @@ -150,7 +150,7 @@ class Container {
this.node.attributes({
'data-placeholder': placeholder,
});
} else if (this.#styleElement)
} else if (this.#styleElement && this.#styleElement.parentNode)
document.body.removeChild(this.#styleElement);
}

Expand Down
8 changes: 8 additions & 0 deletions packages/engine/src/engine/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,14 @@ class Engine implements EngineInterface {
console.log(`confirm:${message}`);
return Promise.reject(false);
}

showPlaceholder() {
this._container.showPlaceholder();
}

hidePlaceholder() {
this._container.hidePlaceholder();
}
}

export default Engine;
4 changes: 3 additions & 1 deletion packages/engine/src/ot/applier.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,10 @@ class Applier implements ApplierInterface {
nodeValue.substring(offset);
if (begine && begine.parentNode === end)
begine.nodeValue = value;
else {
else if (!!value) {
const textNode = document.createTextNode(value);
if (end.firstChild?.nodeName === 'BR')
end.firstChild.remove();
end.insertBefore(textNode, end.firstChild);
}
return node;
Expand Down
78 changes: 40 additions & 38 deletions packages/engine/src/ot/creator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { $ } from '../node';
import {
CARD_ASYNC_RENDER,
DATA_ELEMENT,
DATA_TRANSIENT_ELEMENT,
ROOT,
UI_SELECTOR,
} from '../constants';
Expand Down Expand Up @@ -247,7 +248,7 @@ class Creator extends EventEmitter2 {
attrOps.push({
path,
oldPath,
newValue: target['data'],
newValue: record['text-data'] || target['data'],
});
isDataString = true;
}
Expand Down Expand Up @@ -422,13 +423,14 @@ class Creator extends EventEmitter2 {
}
});
//所有的UI子节点
container
.find(`${UI_SELECTOR}`)
.allChildren()
.forEach((child) => {
const uiElements = container.find(`${UI_SELECTOR}`);
uiElements.each((_, index) => {
const ui = uiElements.eq(index);
ui?.allChildren().forEach((child) => {
if (child.type === getDocument().ELEMENT_NODE)
this.cacheTransientElements?.push(child[0]);
});
});
}
records = records.filter(
(record) =>
Expand All @@ -445,39 +447,39 @@ class Creator extends EventEmitter2 {
}

normalizeOps(ops: Op[]) {
if (this.engine.change.isComposing()) {
if (
ops.length === 2 &&
'ld' in ops[1] &&
ops[1].ld[0] &&
'li' in ops[0] &&
typeof ops[0].li === 'string'
) {
this.lineStart = true;
ops.splice(0, 1);
//ops[0].li = '';
this.readyToEmitOps(ops);
return;
}
if (ops.length === 1 && isCursorOp(ops[0])) return;
if (ops.length === 2 && 'si' in ops[0] && isEqual(ops[0], ops[1]))
ops.splice(1, 1);
this.laterOps = ops;
if (this.timer) clearTimeout(this.timer);
this.timer = setTimeout(() => {
if (!this.engine.change.isComposing()) {
if (this.lineStart) {
this.engine.history.startCache(10);
this.lineStart = false;
}
if (this.laterOps) {
this.readyToEmitOps(this.laterOps);
this.laterOps = null;
}
this.timer = null;
}
}, 0);
}
// if (this.engine.change.isComposing()) {
// if (
// ops.length === 2 &&
// 'ld' in ops[1] &&
// ops[1].ld[0] &&
// 'li' in ops[0] &&
// typeof ops[0].li === 'string'
// ) {
// this.lineStart = true;
// ops.splice(0, 1);
// if(ops[0].li) ops[0].li = '';
// this.readyToEmitOps(ops);
// return;
// }
// if (ops.length === 1 && isCursorOp(ops[0])) return;
// if (ops.length === 2 && 'si' in ops[0] && isEqual(ops[0], ops[1]))
// ops.splice(1, 1);
// this.laterOps = ops;
// if (this.timer) clearTimeout(this.timer);
// this.timer = setTimeout(() => {
// if (!this.engine.change.isComposing()) {
// if (this.lineStart) {
// this.engine.history.startCache(10);
// this.lineStart = false;
// }
// if (this.laterOps) {
// this.readyToEmitOps(this.laterOps);
// this.laterOps = null;
// }
// this.timer = null;
// }
// }, 0);
// }
if (this.laterOps) {
const equal = isEqual(this.laterOps, ops);
this.readyToEmitOps(this.laterOps);
Expand Down
9 changes: 9 additions & 0 deletions packages/engine/src/ot/mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,16 @@ class Mutation extends EventEmitter2 implements MutationInterface {
submitCache() {
if (this.isCache) {
setTimeout(() => {
if (this.engine.change.isComposing()) return;
this.isCache = false;
this.cache = this.cache.map((record) => {
if (record.type === 'characterData') {
if (record.target.nodeType === document.TEXT_NODE) {
record['text-data'] = record.target.textContent;
}
}
return record;
});
if (this.cache.length > 0)
this.creator.handleMutations(this.cache);
this.cache = [];
Expand Down
8 changes: 8 additions & 0 deletions packages/engine/src/types/engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,14 @@ export interface EngineInterface extends EditorInterface {
* 获取JSON格式的值
*/
getJsonValue(): string | undefined | (string | {})[];
/**
* 展示 placeholder
*/
showPlaceholder(): void;
/**
* 隐藏 placeholder
*/
hidePlaceholder(): void;
/**
* 绑定事件
* @param eventType 事件类型
Expand Down
4 changes: 3 additions & 1 deletion plugins/table/src/component/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,9 @@ class Helper implements HelperInterface {
const colElement = cols[c] as HTMLTableColElement;
const _width = cols.eq(c)?.attributes('width');
if (_width) {
cols.eq(c)?.attributes('width', parseInt(_width));
const widthValue = parseInt(_width);
if (widthValue !== NaN)
cols.eq(c)?.attributes('width', widthValue);
}

if (colElement.span > 1) {
Expand Down
2 changes: 1 addition & 1 deletion site-ssr/app/data/doc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"id": "demo",
"content": {
"value": "<ul class=\"data-list data-list-task\" data-id=\"u458facb3-2935278801384898fc08a\"><li class=\"data-list-item\" data-id=\"l777b64a0-2935278801384898fc08a\"><card type=\"inline\" name=\"checkbox\" value=\"data:%7B%22id%22%3A%228Syo3%22%2C%22checked%22%3Afalse%2C%22type%22%3A%22inline%22%7D\"></card>dfd3434</li><li class=\"data-list-item\" data-id=\"l5fcd2ef1-293528029773a54df97d2\"><card type=\"inline\" name=\"checkbox\" value=\"data:%7B%22id%22%3A%22SqHA4%22%2C%22checked%22%3Afalse%2C%22type%22%3A%22inline%22%7D\"></card>23sdfdfsdf</li><li class=\"data-list-item\" data-id=\"l22a0d9aa-293613426361e0228f6f1\"><card type=\"inline\" name=\"checkbox\" value=\"data:%7B%22id%22%3A%22nYic3%22%2C%22type%22%3A%22inline%22%7D\"></card>sdf</li><li class=\"data-list-item\" data-id=\"ld7af09c3-29361357670420bd7bc20\"><card type=\"inline\" name=\"checkbox\" value=\"data:%7B%22id%22%3A%22QDS8g%22%2C%22type%22%3A%22inline%22%7D\"></card>dfsdfdfsdfdf</li><li class=\"data-list-item\" data-id=\"l22a0d9aa-29361322328414cd7707d\"><card type=\"inline\" name=\"checkbox\" value=\"data:%7B%22id%22%3A%2249Kad%22%2C%22type%22%3A%22inline%22%7D\"></card>df</li></ul><p data-id=\"peafa3674-29353388612879c2aa938\">sdf</p><ul class=\"data-list data-list-task\" data-id=\"u458facb3-2935278801384898fc08a\"><li class=\"data-list-item\" data-id=\"l22a0d9aa-29352818185f70cfe4e0b\"><card type=\"inline\" name=\"checkbox\" value=\"data:%7B%22id%22%3A%22d8AR3%22%2C%22checked%22%3Afalse%2C%22type%22%3A%22inline%22%7D\"></card>dfs</li><li class=\"data-list-item\" data-id=\"l777b64a0-2936287482005b34308a5\"><card type=\"inline\" name=\"checkbox\" value=\"data:%7B%22id%22%3A%22na6B8%22%2C%22type%22%3A%22inline%22%7D\"></card>sdfsdfgff</li></ul><blockquote data-id=\"bb9e78d9b-29354165021070af22614\"><p data-id=\"peafa3674-293533981328c42414026\" style=\"text-indent: 2em;\">sdfdfs</p></blockquote><card type=\"block\" name=\"table\" value=\"data:%7B%22rows%22%3A3%2C%22cols%22%3A3%2C%22id%22%3A%22zfiEm%22%2C%22height%22%3A102%2C%22width%22%3A690%2C%22html%22%3A%22%3Ctable%20class%3D%5C%22data-table%5C%22%20data-id%3D%5C%22t21b6db5f-2935357078032113fbbf1%5C%22%20style%3D%5C%22width%3A%20690px%3B%5C%22%3E%3Ccolgroup%20data-id%3D%5C%22c9d5c425f-2935357078032113fbbf1%5C%22%3E%3Ccol%20data-id%3D%5C%22c5da68794-2935357078104d7d2b721%5C%22%20width%3D%5C%22230%5C%22%20span%3D%5C%221%5C%22%3E%3C%2Fcol%3E%3Ccol%20data-id%3D%5C%22c5da68794-29353570781250e9921f4%5C%22%20width%3D%5C%22230%5C%22%20span%3D%5C%221%5C%22%3E%3C%2Fcol%3E%3Ccol%20data-id%3D%5C%22c5da68794-293535707815977193d3a%5C%22%20width%3D%5C%22230%5C%22%20span%3D%5C%221%5C%22%3E%3C%2Fcol%3E%3C%2Fcolgroup%3E%3Ctbody%20data-id%3D%5C%22t61d5e3c3-2935357078104d7d2b721%5C%22%3E%3Ctr%20data-id%3D%5C%22t8f119737-2935357078104d7d2b721%5C%22%20style%3D%5C%22height%3A%2033px%3B%5C%22%3E%3Ctd%20data-id%3D%5C%22td18b0d53-2935357078104d7d2b721%5C%22%3E%3Cp%20data-id%3D%5C%22peafa3674-293610999349011162a65%5C%22%3Esdfsdf%3C%2Fp%3E%3C%2Ftd%3E%3Ctd%20data-id%3D%5C%22td18b0d53-29353570782b27625c5c6%5C%22%3E%3Cp%20data-id%3D%5C%22peafa3674-293535707820779f41768%5C%22%3Esdfdsf%3C%2Fp%3E%3C%2Ftd%3E%3Ctd%20data-id%3D%5C%22td18b0d53-2935357078311d0468944%5C%22%20class%3D%5C%22table-last-row%5C%22%20rowspan%3D%5C%221%5C%22%20colspan%3D%5C%221%5C%22%3E%3Cp%20data-id%3D%5C%22peafa3674-29353570783f9b2ea0d38%5C%22%3E%3Cbr%20%2F%3E%3C%2Fp%3E%3C%2Ftd%3E%3C%2Ftr%3E%3Ctr%20data-id%3D%5C%22t8f119737-29353570784be4f69e482%5C%22%20style%3D%5C%22height%3A%2033px%3B%5C%22%3E%3Ctd%20data-id%3D%5C%22td18b0d53-29353570784ee527a1a8f%5C%22%20rowspan%3D%5C%221%5C%22%20colspan%3D%5C%222%5C%22%3E%3Cp%20data-id%3D%5C%22peafa3674-29361099934bd7d6d5eaa%5C%22%3Esdfdf%3C%2Fp%3E%3C%2Ftd%3E%3Ctd%20class%3D%5C%22table-last-row%5C%22%3E%3Cp%3E%3Cbr%20%2F%3E%3C%2Fp%3E%3C%2Ftd%3E%3C%2Ftr%3E%3Ctr%20data-id%3D%5C%22t8f119737-29353570787258fadb0d3%5C%22%20style%3D%5C%22height%3A%2033px%3B%5C%22%3E%3Ctd%20data-id%3D%5C%22td18b0d53-293535707879e71afbb85%5C%22%20class%3D%5C%22table-last-column%5C%22%3E%3Cp%20data-id%3D%5C%22peafa3674-29353570787d76cfe6d16%5C%22%3Esdfsdfsdf%3C%2Fp%3E%3C%2Ftd%3E%3Ctd%20data-id%3D%5C%22td18b0d53-2935357078943e8f2900f%5C%22%20class%3D%5C%22table-last-column%5C%22%3E%3Cp%20data-id%3D%5C%22peafa3674-29353570789036dfb17e8%5C%22%3Esdf%3C%2Fp%3E%3C%2Ftd%3E%3Ctd%20class%3D%5C%22table-last-column%20table-last-row%5C%22%3E%3Cp%3E%3Cbr%20%2F%3E%3C%2Fp%3E%3C%2Ftd%3E%3C%2Ftr%3E%3C%2Ftbody%3E%3C%2Ftable%3E%22%2C%22type%22%3A%22block%22%7D\"></card><h2 data-id=\"hc09c2c9d-293543439946818829cd7\" id=\"hc09c2c9d-293543439946818829cd7\">jjj</h2><p data-id=\"peafa3674-29358425163ec81fb7451\">sdf</p><p data-id=\"p65a87c49-293613001961e689738a6\">dfdsd</p><h2 data-id=\"hc09c2c9d-30330476249f14aa6b8a1\" id=\"hc09c2c9d-30330476249f14aa6b8a1\">sdfsdfsdfdsfdfsdf<span style=\"background-color: #73D13D;\">dgdfgfdgasd</span>sfsdfdsfsdfdfdfgfg</h2><p data-id=\"peafa3674-29361296539cec5cdf0fe\">dsdfdf<span style=\"background-color: #73D13D;\">sdfsdf<span style=\"font-size: 40px;\">sdfsdfdsfdfdfgsdfdsfdsfdgfgfdgfdgdfgfdgfdgfg</span></span></p><p data-id=\"pe9564f0f-293584251634c14df7602\">sdh<strong>fgbb</strong><span style=\"background-color: #52C41A;\"><strong>g</strong></span><span style=\"background-color: #52C41A;\"><strong>g<em>d</em>d</strong></span><span style=\"background-color: #52C41A;\"><strong>g</strong></span><span style=\"background-color: #52C41A;\"><strong>gg</strong></span><span style=\"font-size: 48px;\">s似懂非懂分</span></p><p data-id=\"peafa3674-3033959491153a9643d00\" style=\"line-height: 3;\">sdf<code><span style=\"background-color: #FADB14;\">dsfd</span></code><span style=\"background-color: #FADB14;\">sgf<em>dgsdfsf</em></span><code><span style=\"font-size: 48px;\"><span style=\"background-color: #FADB14;\">dsdfdf</span>gfvdfgfdgfgfgfsdfdfdfffffffffffffff</span></code><span style=\"font-size: 48px;\">gfdgdfg</span>hgfh</p><p data-id=\"peafa3674-3034027526334fd197e44\"><br /></p><p data-id=\"peafa3674-303402760725c6917b12d\"><span style=\"font-size: 48px;\">gh</span><a target=\"_blank\" href=\"wwww\"><span style=\"font-size: 48px;\">gfhgsdfdfdfdff</span></a><span style=\"font-size: 48px;\">hg</span>fh</p><p data-id=\"p2ce54e90-293584251634c14df7602\"><br /></p><p data-id=\"peafa3674-2935298602060fef80f88\"><br /></p><p data-id=\"peafa3674-29352814407da3fd1e9fd\"><br /></p>",
"value": "<p data-id=\"peafa0b28-326743239574d38339e11\">132</p>",
"paths": []
}
}

0 comments on commit 1098559

Please sign in to comment.