人生は難しい
条件:Slateをアップグレードしない
問題0:IME入力が機能しない 解決策:特定のパターンに問題があり、それを処理
const onChange: OnChangeFn = (change) => {
// it's a workaround to fix typing issue in slate
if (
change.operations.size === 4 &&
// focus
change.operations.get(0).type === "set_selection" &&
// move to next one (offset +1)
// should be in the end, not here
change.operations.get(1).type === "set_selection" &&
// remove current text
change.operations.get(2).type === "remove_text" &&
// insert new text with typed charter
change.operations.get(3).type === "insert_text"
) {
articleStore.editor.applyOperation(change.operations.get(1));
}
// console.log("onChange updateActiveArticleValue");
articleStore.updateActiveArticleValue(change.value);
};
問題1:IME入力時のアンカーが常に先頭にある
解決策:onKeyDown
、onChange
、onCompositionStart
、onCompositionEnd
のSlateハンドラーを無効化し、onCompositionEnd
で手動で値を挿入
const onChange: OnChangeFn = (change) => {
if (isComposingRef.current) {
bufferedChange.current = change;
// console.log("onChange isComposing");
return;
}
// console.log("onChange updateActiveArticleValue");
articleStore.updateActiveArticleValue(change.value);
};
const onKeyDown: EventHook<React.KeyboardEvent> = async (
event,
editor,
next,
) => {
if (isComposingRef.current) {
// console.log("onKeyDown isComposing");
event.preventDefault();
return;
}
return next();
};
onCompositionStart={(event, editor, next) => {
// console.log("onCompositionStart", event);
event.preventDefault();
isComposingRef.current = true;
// next();
}}
onCompositionEnd={(event, editor, next) => {
// console.log("onCompositionEnd", event);
event.preventDefault();
// next();
setTimeout(() => {
isComposingRef.current = false;
}, 50);
}}
問題2:問題1解決後、IME入力が重複する(例:「你好」がエンター押下後「你好你好」になる) 解決策:重複を削除
onCompositionEnd={(event, editor, next) => {
// console.log("onCompositionEnd", event);
event.preventDefault();
if (event.data && event.data.length > 0) {
const composingText = event.data;
// console.log("composingText", composingText);
// 你好
const { selection } = editor.value;
editor.applyOperation({
type: "insert_text",
path: selection.anchor.path,
offset: selection.anchor.offset,
text: composingText,
});
// editor.value here would be "你好你好"
// workaround
editor.deleteBackward(composingText.length);
articleStore.updateActiveArticleValue(editor.value);
}
// next();
// timeout here to disable onChange
setTimeout(() => {
isComposingRef.current = false;
}, 50);
}}