Note

Slate 0.47のIME入力回避策

人生は難しい

条件: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入力時のアンカーが常に先頭にある 解決策:onKeyDownonChangeonCompositionStartonCompositionEndの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);
}}

'25, Jan 26