Skip to content

Commit 4c3857c

Browse files
committed
fix performance in vscode
1 parent 91f571c commit 4c3857c

7 files changed

Lines changed: 78 additions & 263 deletions

File tree

.changeset/real-birds-deny.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@learningmap/learningmap": patch
3+
"learningmap-studio": patch
4+
---
5+
6+
Fix performance in vscode

packages/learningmap/src/LearningMapEditor.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
import { RoadmapData, KeyBindings } from "./types";
55
import { EditorToolbar } from "./EditorToolbar";
66
import { LearningMap } from "./LearningMap";
7-
import { useEditorStore } from "./editorStore";
7+
import { useEditorStore, setPersistence } from "./editorStore";
88
import { WelcomeMessage } from "./WelcomeMessage";
99
import { EditorCanvas } from "./EditorCanvas";
1010
import { EditorDialogs } from "./EditorDialogs";
@@ -17,6 +17,7 @@ export interface LearningMapEditorProps {
1717
jsonStore?: string;
1818
disableSharing?: boolean;
1919
disableFileOperations?: boolean;
20+
disablePersist?: boolean;
2021
keyBindings?: Partial<KeyBindings>;
2122
}
2223

@@ -26,6 +27,7 @@ export function LearningMapEditor({
2627
jsonStore = "https://json.openpatch.org",
2728
disableSharing = false,
2829
disableFileOperations = false,
30+
disablePersist = false,
2931
keyBindings,
3032
}: LearningMapEditorProps) {
3133
// Only get minimal state needed in this component
@@ -43,6 +45,10 @@ export function LearningMapEditor({
4345
// Use language from settings if available, otherwise use prop
4446
const effectiveLanguage = settings?.language || language;
4547

48+
useEffect(() => {
49+
setPersistence(!disablePersist);
50+
}, [disablePersist]);
51+
4652
useEffect(() => {
4753
setJsonStore(jsonStore);
4854
setDefaultLanguage(language);

packages/learningmap/src/editorStore.ts

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ import {
1818
import { NodeData, RoadmapData, Settings } from "./types";
1919
import { getZIndexForNodeType } from "./zIndexHelper";
2020

21+
// Global flag to control persistence
22+
let persistenceEnabled = true;
23+
24+
export function setPersistence(enabled: boolean) {
25+
persistenceEnabled = enabled;
26+
}
27+
2128
// Note: This is a global store for the editor. Typically only one editor instance is active at a time.
2229
// If you need multiple independent editor instances, consider creating store instances per component or using context.
2330
export interface EditorState {
@@ -133,6 +140,50 @@ const initialState = {
133140
showUnlockAfter: true,
134141
};
135142

143+
// Temporal middleware configuration
144+
const temporalConfig = {
145+
// Temporal middleware options - throttle undo history to improve drag performance
146+
equality: (oldState: any, newState: any) => isDeepEqual(oldState, newState),
147+
handleSet: (handleSet: any) =>
148+
throttle<typeof handleSet>(
149+
500,
150+
(state: any) => {
151+
handleSet(state);
152+
},
153+
{ noLeading: false, noTrailing: true },
154+
),
155+
partialize: (state: EditorState) => {
156+
const { nodes, edges, settings } = state;
157+
return { nodes, edges, settings };
158+
},
159+
};
160+
161+
// Persist middleware configuration
162+
const persistConfig = {
163+
name: "learningmap-data", // name of the item in storage
164+
version: 1,
165+
partialize: (state: EditorState) => {
166+
const { nodes, edges, settings } = state;
167+
return { nodes, edges, settings };
168+
},
169+
storage: {
170+
getItem: (name: string) => {
171+
if (!persistenceEnabled) return null;
172+
const str = localStorage.getItem(name);
173+
return str ? JSON.parse(str) : null;
174+
},
175+
setItem: (name: string, value: any) => {
176+
if (!persistenceEnabled) return;
177+
localStorage.setItem(name, JSON.stringify(value));
178+
},
179+
removeItem: (name: string) => {
180+
if (!persistenceEnabled) return;
181+
localStorage.removeItem(name);
182+
},
183+
},
184+
} as const;
185+
186+
// Create the store with conditional persistence
136187
export const useEditorStore = create<EditorState>()(
137188
persist(
138189
temporal(
@@ -382,8 +433,8 @@ export const useEditorStore = create<EditorState>()(
382433
if (nodesArr.length > 0) {
383434
const maxId = Math.max(
384435
...nodesArr
385-
.map((n) => parseInt(n.id.replace(/\D/g, ""), 10))
386-
.filter((id) => !isNaN(id)),
436+
.map((n: any) => parseInt(n.id.replace(/\D/g, ""), 10))
437+
.filter((id: number) => !isNaN(id)),
387438
);
388439
nextNodeId = maxId + 1;
389440
}
@@ -401,7 +452,7 @@ export const useEditorStore = create<EditorState>()(
401452
getRoadmapData: () => {
402453
const state = get();
403454
return {
404-
nodes: state.nodes.map((n) => ({
455+
nodes: state.nodes.map((n: any) => ({
405456
id: n.id,
406457
type: n.type,
407458
position: n.position,
@@ -414,8 +465,8 @@ export const useEditorStore = create<EditorState>()(
414465
data: n.data,
415466
})),
416467
edges: state.edges
417-
.filter((e) => !e.id.startsWith("debug-"))
418-
.map((e) => ({
468+
.filter((e: any) => !e.id.startsWith("debug-"))
469+
.map((e: any) => ({
419470
id: e.id,
420471
source: e.source,
421472
target: e.target,
@@ -446,39 +497,17 @@ export const useEditorStore = create<EditorState>()(
446497
set(initialState);
447498
},
448499
}),
449-
{
450-
// Temporal middleware options - throttle undo history to improve drag performance
451-
equality: (oldState, newState) => isDeepEqual(oldState, newState),
452-
handleSet: (handleSet) =>
453-
throttle<typeof handleSet>(
454-
500,
455-
(state) => {
456-
handleSet(state);
457-
},
458-
{ noLeading: false, noTrailing: true },
459-
),
460-
partialize: (state): any => {
461-
const { nodes, edges, settings } = state;
462-
return { nodes, edges, settings };
463-
},
464-
},
500+
temporalConfig,
465501
),
466-
{
467-
name: "learningmap-data", // name of the item in storage
468-
version: 1,
469-
partialize: (state) => {
470-
const { nodes, edges, settings } = state;
471-
return { nodes, edges, settings };
472-
},
473-
},
502+
persistConfig,
474503
),
475504
);
476505

477506
type PartialEditorState = Pick<EditorState, "nodes" | "edges" | "settings">;
478507

479508
// Hook for accessing temporal store (undo/redo)
480509
export function useTemporalStore<T>(
481-
selector?: (state: TemporalState<PartialEditorState>) => T,
510+
selector?: (state: TemporalState<any>) => T,
482511
equality?: (a: T, b: T) => boolean,
483512
) {
484513
return useStoreWithEqualityFn(useEditorStore.temporal, selector!, equality);

packages/learningmap/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ export type { RoadmapData, RoadmapState, KeyBindings, KeyBinding } from "./types
55
export type { LearningMapProps } from "./LearningMap";
66
export type { LearningMapEditorProps } from "./LearningMapEditor";
77
export { LearningMap, LearningMapEditor };
8-
export { useEditorStore, useTemporalStore } from "./editorStore";
8+
export { useEditorStore, useTemporalStore, setPersistence } from "./editorStore";
99
export { useViewerStore } from "./viewerStore";
1010
export { useFileOperations } from "./useFileOperations";

platforms/vscode/package.json

Lines changed: 0 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -158,140 +158,6 @@
158158
"title": "Show Help",
159159
"category": "Learningmap"
160160
}
161-
],
162-
"keybindings": [
163-
{
164-
"command": "learningmap.showSource",
165-
"key": "ctrl+k ctrl+s",
166-
"mac": "cmd+k cmd+s",
167-
"when": "resourceExtname == .learningmap"
168-
},
169-
{
170-
"command": "learningmap.addTaskNode",
171-
"key": "ctrl+1",
172-
"mac": "cmd+1",
173-
"when": "activeCustomEditorId == learningmap.editor"
174-
},
175-
{
176-
"command": "learningmap.addTopicNode",
177-
"key": "ctrl+2",
178-
"mac": "cmd+2",
179-
"when": "activeCustomEditorId == learningmap.editor"
180-
},
181-
{
182-
"command": "learningmap.addImageNode",
183-
"key": "ctrl+3",
184-
"mac": "cmd+3",
185-
"when": "activeCustomEditorId == learningmap.editor"
186-
},
187-
{
188-
"command": "learningmap.addTextNode",
189-
"key": "ctrl+4",
190-
"mac": "cmd+4",
191-
"when": "activeCustomEditorId == learningmap.editor"
192-
},
193-
{
194-
"command": "learningmap.undo",
195-
"key": "ctrl+z",
196-
"mac": "cmd+z",
197-
"when": "activeCustomEditorId == learningmap.editor"
198-
},
199-
{
200-
"command": "learningmap.redo",
201-
"key": "ctrl+y",
202-
"mac": "cmd+y",
203-
"when": "activeCustomEditorId == learningmap.editor"
204-
},
205-
{
206-
"command": "learningmap.togglePreview",
207-
"key": "ctrl+p",
208-
"mac": "cmd+p",
209-
"when": "activeCustomEditorId == learningmap.editor"
210-
},
211-
{
212-
"command": "learningmap.toggleDebug",
213-
"key": "ctrl+d",
214-
"mac": "cmd+d",
215-
"when": "activeCustomEditorId == learningmap.editor"
216-
},
217-
{
218-
"command": "learningmap.zoomIn",
219-
"key": "ctrl+=",
220-
"mac": "cmd+=",
221-
"when": "activeCustomEditorId == learningmap.editor"
222-
},
223-
{
224-
"command": "learningmap.zoomOut",
225-
"key": "ctrl+-",
226-
"mac": "cmd+-",
227-
"when": "activeCustomEditorId == learningmap.editor"
228-
},
229-
{
230-
"command": "learningmap.resetZoom",
231-
"key": "ctrl+0",
232-
"mac": "cmd+0",
233-
"when": "activeCustomEditorId == learningmap.editor"
234-
},
235-
{
236-
"command": "learningmap.toggleGrid",
237-
"key": "ctrl+'",
238-
"mac": "cmd+'",
239-
"when": "activeCustomEditorId == learningmap.editor"
240-
},
241-
{
242-
"command": "learningmap.resetMap",
243-
"key": "ctrl+delete",
244-
"mac": "cmd+delete",
245-
"when": "activeCustomEditorId == learningmap.editor"
246-
},
247-
{
248-
"command": "learningmap.cut",
249-
"key": "ctrl+x",
250-
"mac": "cmd+x",
251-
"when": "activeCustomEditorId == learningmap.editor"
252-
},
253-
{
254-
"command": "learningmap.copy",
255-
"key": "ctrl+c",
256-
"mac": "cmd+c",
257-
"when": "activeCustomEditorId == learningmap.editor"
258-
},
259-
{
260-
"command": "learningmap.paste",
261-
"key": "ctrl+v",
262-
"mac": "cmd+v",
263-
"when": "activeCustomEditorId == learningmap.editor"
264-
},
265-
{
266-
"command": "learningmap.selectAll",
267-
"key": "ctrl+a",
268-
"mac": "cmd+a",
269-
"when": "activeCustomEditorId == learningmap.editor"
270-
},
271-
{
272-
"command": "learningmap.fitView",
273-
"key": "shift+1",
274-
"mac": "shift+1",
275-
"when": "activeCustomEditorId == learningmap.editor"
276-
},
277-
{
278-
"command": "learningmap.zoomToSelection",
279-
"key": "shift+2",
280-
"mac": "shift+2",
281-
"when": "activeCustomEditorId == learningmap.editor"
282-
},
283-
{
284-
"command": "learningmap.deleteSelected",
285-
"key": "delete",
286-
"mac": "delete",
287-
"when": "activeCustomEditorId == learningmap.editor"
288-
},
289-
{
290-
"command": "learningmap.help",
291-
"key": "ctrl+shift+/",
292-
"mac": "cmd+shift+/",
293-
"when": "activeCustomEditorId == learningmap.editor"
294-
}
295161
]
296162
},
297163
"scripts": {

platforms/vscode/src/extension.ts

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -111,39 +111,6 @@ export function activate(context: vscode.ExtensionContext) {
111111
})
112112
);
113113

114-
// Register editor commands that send messages to the webview
115-
const editorCommands = [
116-
'addTaskNode',
117-
'addTopicNode',
118-
'addImageNode',
119-
'addTextNode',
120-
'undo',
121-
'redo',
122-
'togglePreview',
123-
'toggleDebug',
124-
'zoomIn',
125-
'zoomOut',
126-
'resetZoom',
127-
'toggleGrid',
128-
'resetMap',
129-
'cut',
130-
'copy',
131-
'paste',
132-
'selectAll',
133-
'fitView',
134-
'zoomToSelection',
135-
'deleteSelected',
136-
'help',
137-
];
138-
139-
editorCommands.forEach(command => {
140-
context.subscriptions.push(
141-
vscode.commands.registerCommand(`learningmap.${command}`, () => {
142-
provider.sendCommandToActiveEditor(command);
143-
})
144-
);
145-
});
146-
147114
console.log('Learningmap extension is now active');
148115
}
149116

0 commit comments

Comments
 (0)