1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-30 10:36:35 +02:00

Desktop: Manually refresh codemirror whenever the window size changes (#3388)

* Manually refresh codemirror whenever the parent div size changes

* Set editor width through style rather than adding an extra property

* use Memo for editorStyle
This commit is contained in:
Caleb John 2020-07-02 15:45:43 -06:00 committed by GitHub
parent a9390affaa
commit 8eb94bc8ab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 3 deletions

View File

@ -5,7 +5,7 @@ import { useState, useEffect, useRef, forwardRef, useCallback, useImperativeHand
import { EditorCommand, NoteBodyEditorProps } from '../../utils/types';
import { commandAttachFileToBody, handlePasteEvent } from '../../utils/resourceHandling';
import { ScrollOptions, ScrollOptionTypes } from '../../utils/types';
import { useScrollHandler, usePrevious, cursorPositionToTextOffset } from './utils';
import { useScrollHandler, usePrevious, cursorPositionToTextOffset, useRootSize } from './utils';
import Toolbar from './Toolbar';
import styles_ from './styles';
import { RenderedBody, defaultRenderedBody } from './utils/types';
@ -48,6 +48,8 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
const contentKeyHasChangedRef = useRef(false);
contentKeyHasChangedRef.current = previousContentKey !== props.contentKey;
const rootSize = useRootSize({ rootRef });
const { resetScroll, editor_scroll, setEditorPercentScroll, setViewerPercentScroll } = useScrollHandler(editorRef, webviewRef, props.onScroll);
const cancelledKeys: {mac: string[], default: string[]} = { mac: [], default: [] };
@ -367,9 +369,23 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
return output;
}, [styles.cellViewer, props.visiblePanes]);
// The editor needs to be kept up to date on the actual space that it's filling
// Ogherwise we can get some rendering errors when the editor size is changed
// (this can happen when switching layout of when toggling sidebars for example)
const editorStyle = useMemo(() => {
const output = Object.assign({}, rootSize, styles.editor);
if (props.visiblePanes.includes('editor') && props.visiblePanes.includes('viewer')) {
output.width = Math.floor(rootSize.width / 2);
}
return output;
}, [rootSize, styles.editor, props.visiblePanes]);
const editorReadOnly = props.visiblePanes.indexOf('editor') < 0;
function renderEditor() {
return (
<div style={cellEditorStyle}>
<Editor
@ -377,7 +393,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
ref={editorRef}
mode={props.contentMarkupLanguage === Note.MARKUP_LANGUAGE_HTML ? 'xml' : 'gfm'}
theme={styles.editor.codeMirrorTheme}
style={styles.editor}
style={editorStyle}
readOnly={props.visiblePanes.indexOf('editor') < 0}
autoMatchBraces={Setting.value('editor.autoMatchingBraces')}
keyMap={props.keyboardMode}

View File

@ -184,6 +184,18 @@ function Editor(props: EditorProps, ref: any) {
}
}, [props.value, props.theme, props.mode, props.readOnly, props.autoMatchBraces, props.keyMap]);
useEffect(() => {
if (editor) {
// Need to let codemirror know that it's container's size has changed so that it can
// re-compute anything it needs to. This ensures the cursor (and anything that is
// based on window size will be correct
// Manually calling refresh here will cause a double refresh in some instances (when the
// windows size is changed for example) but this is a fairly quick operation so it's worth
// it.
editor.refresh();
}
}, [props.style.width, props.style.height]);
return <div style={props.style} ref={editorParent} />;
}

View File

@ -1,4 +1,4 @@
import { useEffect, useCallback, useRef } from 'react';
import { useEffect, useCallback, useRef, useState } from 'react';
export function cursorPositionToTextOffset(cursorPos: any, body: string) {
if (!body) return 0;
@ -82,3 +82,22 @@ export function useScrollHandler(editorRef: any, webviewRef: any, onScroll: Func
return { resetScroll, setEditorPercentScroll, setViewerPercentScroll, editor_scroll };
}
export function useRootSize(dependencies:any) {
const { rootRef } = dependencies;
const [rootSize, setRootSize] = useState({ width: 0, height: 0 });
useEffect(() => {
if (!rootRef.current) return;
const { width, height } = rootRef.current.getBoundingClientRect();
if (rootSize.width !== width || rootSize.height !== height) {
setRootSize({ width: width, height: height });
}
});
return rootSize;
}