Skip to content

Commit

Permalink
Fix an editor sync scroll issue
Browse files Browse the repository at this point in the history
  • Loading branch information
tylerlong committed Oct 8, 2024
1 parent 52ce15c commit 639573b
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 14 deletions.
15 changes: 12 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,18 @@ const main = async () => {
// scroll to hash element
if (window.location.hash.length > 0) {
const previewPanel = document.querySelector('.ui-layout-east');
const linkElement = document.querySelector(window.location.hash);
if (previewPanel && linkElement) {
previewPanel.scrollTop = (linkElement as HTMLElement).offsetTop;
const linkElement = document.querySelector(
window.location.hash,
) as HTMLElement;
if (linkElement) {
previewPanel.scrollTop = linkElement.offsetTop;
// first time scroll `store.editor.heightAtLine(xxx, 'local')` value is wrong
// trigger again after 300ms
// it is a codemirror bug, maybe latest version has fixed this issue
setTimeout(() => {
previewPanel.scrollTop = linkElement.offsetTop - 1;
previewPanel.scrollTop = linkElement.offsetTop;
}, 300);
}
}
}, 3000);
Expand Down
34 changes: 23 additions & 11 deletions src/sync_scroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ import $ from 'jquery';
import debounce from 'lodash/debounce';
import store from './store';

type IScroll = {
lastMarker: number;
nextMarker: number;
percentage: number;
};

let scrollingSide = null;
let timeoutHandle = null;
const scrollSide = (side, howToScroll) => {
const scrollSide = (side: 'left' | 'right', howToScroll): void => {
if (scrollingSide !== null && scrollingSide !== side) {
return; // the other side hasn't finished scrolling
}
Expand All @@ -16,12 +22,12 @@ const scrollSide = (side, howToScroll) => {
howToScroll();
};

const scrollEditor = (scrollTop, when) => {
const scrollEditor = (scrollTop: number, when: number): void => {
setTimeout(() => {
store.editor.scrollTo(null, scrollTop);
}, when);
};
const scrollLeft = (scrollTop) => {
const scrollLeft = (scrollTop: number): void => {
scrollSide('left', () => {
const current = store.editor.getScrollInfo().top;
const step = (scrollTop - current) / 8;
Expand All @@ -33,13 +39,13 @@ const scrollLeft = (scrollTop) => {
});
};

const scrollRight = (scrollTop) => {
const scrollRight = (scrollTop: number): void => {
scrollSide('right', () => {
$('.ui-layout-east').animate({ scrollTop: scrollTop }, 128);
});
};

const getEditorScroll = () => {
const getEditorScroll = (): IScroll => {
const lineMarkers = $('article#preview > [data-source-line]');
const lines = [];
lineMarkers.each((index, element) => {
Expand All @@ -66,10 +72,11 @@ const getEditorScroll = () => {
store.editor.heightAtLine(lastMarker - 1, 'local'));
}
// returns two neighboring markers' lines, and current scroll percentage between two markers
return { lastMarker: lastMarker, nextMarker: nextMarker, percentage };
const r = { lastMarker: lastMarker, nextMarker: nextMarker, percentage };
return r;
};

const setPreviewScroll = (editorScroll) => {
const setPreviewScroll = (editorScroll: IScroll) => {
let lastPosition = 0;
let nextPosition =
$('article#preview').outerHeight() - $('.ui-layout-east').height(); // maximum scroll
Expand All @@ -90,8 +97,8 @@ const setPreviewScroll = (editorScroll) => {
scrollRight(scrollTop);
};

const getPreviewScroll = () => {
const scroll = $('.ui-layout-east').scrollTop();
const getPreviewScroll = (): IScroll => {
const scroll = document.querySelector('.ui-layout-east').scrollTop;
let lastLine = 0;
let lastScroll = 0;
let nextLine = store.editor.getValue().split('\n').length; // number of lines of markdown
Expand All @@ -114,10 +121,15 @@ const getPreviewScroll = () => {
percentage = (scroll - lastScroll) / (nextScroll - lastScroll);
}
// returns two neighboring marker lines, and current scroll percentage between two markers
return { lastMarker: lastLine, nextMarker: nextLine, percentage: percentage };
const r = {
lastMarker: lastLine,
nextMarker: nextLine,
percentage: percentage,
};
return r;
};

const setEditorScroll = (previewScroll) => {
const setEditorScroll = (previewScroll: IScroll) => {
const last = store.editor.heightAtLine(previewScroll.lastMarker - 1, 'local');
const next = store.editor.heightAtLine(previewScroll.nextMarker - 1, 'local');
scrollLeft((next - last) * previewScroll.percentage + last);
Expand Down

0 comments on commit 639573b

Please sign in to comment.