File size: 2,601 Bytes
c2c8c8d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
import { create } from 'zustand';

interface CursorPosition {
  lineNumber: number;
  column: number;
}

export interface OpenFile {
  path: string;
  content: string;
  isDirty: boolean;
  language: string;
  cursorPosition: CursorPosition;
}

interface EditorState {
  openFiles: Record<string, OpenFile>;
  activeFilePath: string | null;
  recentFiles: string[];
  addFile: (path: string, content: string, language: string) => void;
  removeFile: (path: string) => void;
  setActive: (path: string) => void;
  updateContent: (path: string, content: string) => void;
  markClean: (path: string) => void;
  setCursorPosition: (path: string, position: CursorPosition) => void;
}

export const useEditorStore = create<EditorState>((set, get) => ({
  openFiles: {},
  activeFilePath: null,
  recentFiles: [],

  addFile: (path, content, language) =>
    set((state) => {
      if (state.openFiles[path]) {
        return { activeFilePath: path, recentFiles: [path, ...state.recentFiles.filter((f) => f !== path)].slice(0, 10) };
      }
      return {
        openFiles: {
          ...state.openFiles,
          [path]: { path, content, isDirty: false, language, cursorPosition: { lineNumber: 1, column: 1 } },
        },
        activeFilePath: path,
        recentFiles: [path, ...state.recentFiles.filter((f) => f !== path)].slice(0, 10),
      };
    }),

  removeFile: (path) =>
    set((state) => {
      const { [path]: _, ...rest } = state.openFiles;
      const remainingPaths = Object.keys(rest);
      const activeFilePath = state.activeFilePath === path
        ? remainingPaths[remainingPaths.length - 1] || null
        : state.activeFilePath;
      return { openFiles: rest, activeFilePath };
    }),

  setActive: (path) => set({ activeFilePath: path }),

  updateContent: (path, content) =>
    set((state) => {
      const file = state.openFiles[path];
      if (!file) return state;
      return {
        openFiles: {
          ...state.openFiles,
          [path]: { ...file, content, isDirty: true },
        },
      };
    }),

  markClean: (path) =>
    set((state) => {
      const file = state.openFiles[path];
      if (!file) return state;
      return {
        openFiles: {
          ...state.openFiles,
          [path]: { ...file, isDirty: false },
        },
      };
    }),

  setCursorPosition: (path, position) =>
    set((state) => {
      const file = state.openFiles[path];
      if (!file) return state;
      return {
        openFiles: {
          ...state.openFiles,
          [path]: { ...file, cursorPosition: position },
        },
      };
    }),
}));