Skip to content

Commit bd34f12

Browse files
committed
Add timeout to split-view editor.
1 parent e5b85ea commit bd34f12

File tree

5 files changed

+240
-181
lines changed

5 files changed

+240
-181
lines changed

apps/fluster/src/features/editor/presentation/split_view/split_view_scaffold.tsx

Lines changed: 67 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,79 @@
1-
import React, { type ReactNode } from "react";
1+
import React, { useEffect, useRef, useState, type ReactNode } from "react";
22
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
33
import CodeEditor, { CodeEditorProps } from "../code_editor/main";
44
import { MdxContent } from "#/mdx/presentation/mdx_content";
55
import { MdxNoteBibliographyByContent } from "#/bibliography/presentation/note_bibliography/bib_by_mdx_content";
66
import { MdxProviderGroup } from "#/mdx/presentation/mdx_provider_group";
77

88
interface SplitViewScaffoldProps
9-
extends Omit<CodeEditorProps, "themes" | "isModal" | "vimMode"> {
10-
autoSaveId?: string;
9+
extends Omit<CodeEditorProps, "themes" | "isModal" | "vimMode"> {
10+
autoSaveId?: string;
11+
debounceSeconds: AppState["code"]["previewDebounce"];
1112
}
1213

13-
const SplitViewContainer = ({
14-
onChange,
15-
value,
16-
language,
17-
autoSaveId = "splitview-panels",
18-
...props
19-
}: SplitViewScaffoldProps): ReactNode => {
20-
return (
21-
<PanelGroup autoSaveId={autoSaveId} direction="horizontal">
22-
<Panel id="editor-panel" order={1} defaultSize={50}>
23-
<CodeEditor
24-
{...props}
25-
language={language}
26-
value={value}
27-
onChange={onChange}
28-
/>
29-
</Panel>
30-
<PanelResizeHandle />
31-
<Panel
32-
id="editor-output-panel"
33-
className="bg-background"
34-
order={2}
35-
defaultSize={50}
36-
>
37-
<div
38-
id="mdx-page-container"
39-
className="w-full h-full overflow-y-auto overflow-x-hidden py-16 px-8"
40-
>
41-
<MdxProviderGroup>
42-
<MdxContent
43-
removeGrayMatter
44-
className="p-6 max-h-full contents"
45-
mdx={value}
46-
/>
47-
</MdxProviderGroup>
48-
<MdxNoteBibliographyByContent mdx={value} />
49-
</div>
50-
</Panel>
51-
</PanelGroup>
52-
);
53-
};
14+
import { AppState } from "@/state/initial_state";
15+
import { connect } from "react-redux";
16+
17+
const connector = connect((state: AppState) => ({
18+
debounceSeconds: state.code.previewDebounce,
19+
}));
20+
21+
const SplitViewContainer = connector(
22+
({
23+
onChange,
24+
value,
25+
language,
26+
autoSaveId = "splitview-panels",
27+
debounceSeconds,
28+
...props
29+
}: SplitViewScaffoldProps): ReactNode => {
30+
const timer = useRef<NodeJS.Timeout | null>(null);
31+
const [debouncedValue, setDebouncedValue] = useState(value);
32+
33+
useEffect(() => {
34+
if (timer.current) {
35+
clearTimeout(timer.current);
36+
}
37+
timer.current = setTimeout(() => {
38+
setDebouncedValue(value);
39+
}, debounceSeconds * 1000);
40+
}, [value]);
41+
42+
return (
43+
<PanelGroup autoSaveId={autoSaveId} direction="horizontal">
44+
<Panel id="editor-panel" order={1} defaultSize={50}>
45+
<CodeEditor
46+
{...props}
47+
language={language}
48+
value={value}
49+
onChange={onChange}
50+
/>
51+
</Panel>
52+
<PanelResizeHandle />
53+
<Panel
54+
id="editor-output-panel"
55+
className="bg-background"
56+
order={2}
57+
defaultSize={50}
58+
>
59+
<div
60+
id="mdx-page-container"
61+
className="w-full h-full overflow-y-auto overflow-x-hidden py-16 px-8"
62+
>
63+
<MdxProviderGroup>
64+
<MdxContent
65+
removeGrayMatter
66+
className="p-6 max-h-full contents"
67+
mdx={debouncedValue}
68+
/>
69+
</MdxProviderGroup>
70+
<MdxNoteBibliographyByContent mdx={debouncedValue} />
71+
</div>
72+
</Panel>
73+
</PanelGroup>
74+
);
75+
}
76+
);
5477

5578
SplitViewContainer.displayName = "SplitViewScaffold";
5679

apps/fluster/src/features/editor/state/code_state.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,7 @@ export interface CodeState {
1313
dark: BundledTheme;
1414
light: BundledTheme;
1515
};
16+
/** The debounce timeout in seconds. */
17+
previewDebounce: number;
1618
jupyter: JupyterConfigState;
1719
}
Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
import { CodeState } from "./code_state";
22

33
export const initialCodeState: CodeState = {
4-
keymap: "standard",
5-
defaultLanguage: "python",
6-
theme: {
7-
dark: "dracula",
8-
light: "github-light",
9-
},
10-
jupyter: {
11-
port: 21521,
12-
token: "",
13-
defaultKernelName: "python",
14-
},
4+
keymap: "standard",
5+
defaultLanguage: "python",
6+
theme: {
7+
dark: "dracula",
8+
light: "github-light",
9+
},
10+
jupyter: {
11+
port: 21521,
12+
token: "",
13+
defaultKernelName: "python",
14+
},
15+
previewDebounce: 0.5,
1516
};

apps/fluster/src/features/editor/state/slice.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { initialCodeState } from "./initial_state";
33
import { BundledLanguage, BundledTheme } from "shiki";
44
import { AppState } from "@/state/initial_state";
55
import { JupyterConfigState } from "./code_state";
6+
import { Payload } from "recharts/types/component/DefaultLegendContent";
67

78
const slice = createSlice({
89
name: "code",
@@ -44,6 +45,12 @@ const slice = createSlice({
4445
},
4546
};
4647
},
48+
setPreviewDebounce(state, action: PayloadAction<number>) {
49+
return {
50+
...state,
51+
previewDebounce: action.payload,
52+
};
53+
},
4754
},
4855
});
4956

@@ -52,6 +59,7 @@ export const {
5259
setDefaultLanguage,
5360
setEditorKeymap,
5461
setJupyterState,
62+
setPreviewDebounce,
5563
} = slice.actions;
5664

5765
export default slice.reducer;

0 commit comments

Comments
 (0)