Skip to content

Commit

Permalink
feat: allow edit same name file (#66)
Browse files Browse the repository at this point in the history
* feat: allow delete use file tree and allow keydowm to add

* feat: realize linkage between file tree and editor

* feat: allow edit same name file

* fix: some bug
  • Loading branch information
coderz-w authored Jul 17, 2024
1 parent 9d3329a commit 4a97823
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 51 deletions.
5 changes: 3 additions & 2 deletions src/app/edit/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,16 +94,17 @@ const Page: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const willChangeEditor = editor;
const willChangeEditorId = over.id;

const mathModel = models.filter((model) => model.filename === file.filename);
const mathModel = models.filter((model) => model.id === file.id);

if (mathModel.length > 0) {
mathModel[0].model &&
setActiveModel(mathModel[0].filename, mathModel[0].model, willChangeEditorId);
mathModel[0].model &&
setModels(
{ filename: mathModel[0].filename, value: '', language: 'typescript' },
{ filename: mathModel[0].filename, value: '', language: 'typescript', id: file.id },
mathModel[0].model,
willChangeEditorId,
file.id,
);
willChangeEditor?.setModel(mathModel[0].model);
} else {
Expand Down
8 changes: 4 additions & 4 deletions src/components/edit/tabItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,18 @@ const Tab: React.FC<TabProps> = ({
const handleTabClick = (e: React.MouseEvent<HTMLDivElement>) => {
e.preventDefault();
e.stopPropagation();
setActiveModel(filename, model, editorId);
setActiveModel(id, model, editorId);
editor && editor.setModel(model);
};

const handleTabClose = (e: React.MouseEvent<HTMLSpanElement>) => {
e.preventDefault();
e.stopPropagation();

const newModels = removeModel(filename, editorId);
const newModels = removeModel(id, editorId);

if (newModels && newModels.filename) {
setActiveModel(newModels.filename, newModels.model, editorId);
if (newModels && newModels.id) {
setActiveModel(newModels.id, newModels.model, editorId);
editor && editor.setModel(newModels.model);
} else {
removeAllModel(editorId);
Expand Down
6 changes: 3 additions & 3 deletions src/components/edit/tabbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export const TabBar: React.FC<TabBarProps> = ({ editorId }) => {
useEffect(() => {
setMockModelsForSort(
models.map((item) => {
return { ...item, id: item.filename };
return { ...item };
}),
);
}, [models]);
Expand All @@ -68,9 +68,9 @@ export const TabBar: React.FC<TabBarProps> = ({ editorId }) => {
return (
<TabItem
id={model.id}
key={model.filename}
key={model.id}
filename={model.filename}
active={model.filename === activeModelId}
active={model.id === activeModelId}
editorId={editorId}
setActiveModel={setActiveModel}
editor={editor}
Expand Down
23 changes: 2 additions & 21 deletions src/components/editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,20 @@ import { useDroppable } from '@dnd-kit/core';
import {
useEditorStore,
useMonacoStore,
useModelsStore,
useActiveModelStore,
useActiveEditorStore,
} from '@/store/editorStore';
import { setModelsFromInfo } from '@/components/editor/utils';
import { TabBar } from '@/components/edit/tabbar';

interface CodeEditorProps {
editorId: number;
}

const modelsInfo: any[] = [];

export default function CodeEditor({ editorId }: CodeEditorProps) {
const { getEditor, setEditor } = useEditorStore();
const { setMonaco } = useMonacoStore();
const { setModels } = useModelsStore();
const { activeMap, setActiveModel } = useActiveModelStore();
const { activeEditorId, setActiveEditor } = useActiveEditorStore();
const { activeMap } = useActiveModelStore();
const { setActiveEditor } = useActiveEditorStore();
const thisEditor = getEditor(editorId);
const currentModel = activeMap[editorId];
// console.log(thisEditor);
Expand Down Expand Up @@ -60,20 +55,6 @@ export default function CodeEditor({ editorId }: CodeEditorProps) {
setEditor(editorId, editor);
setMonaco(editorId, monaco);

if (editorId === 0) {
setModelsFromInfo(modelsInfo, monaco, editor, setModels, setActiveModel, editorId);
} else {
const newModel = activeEditorId < 1 ? activeMap[0] : activeMap[1];
newModel.model && setActiveModel(newModel.modelId, newModel.model, editorId);
newModel.model &&
setModels(
{ filename: newModel.modelId, value: '', language: 'typescript' },
newModel.model,
editorId,
);
editor.setModel(newModel.model);
}

monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
noSemanticValidation: false,
noSyntaxValidation: false,
Expand Down
20 changes: 15 additions & 5 deletions src/components/editor/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ export function setModelsFromInfo(
modelsInfo: modelInfoType[],
monaco: typeof monacoForType,
editor: editor.IStandaloneCodeEditor,
setModels: (modelInfo: modelInfoType, model: editor.ITextModel, editorId: number) => void,
setModels: (
modelInfo: modelInfoType,
model: editor.ITextModel,
editorId: number,
id: string,
) => void,
setActiveModel: (modelId: string, model: editor.ITextModel, editorId: number) => void,
editorId: number,
) {
Expand All @@ -19,16 +24,21 @@ export function addNewModel(
modelInfo: modelInfoType,
monaco: typeof monacoForType,
editor: editor.IStandaloneCodeEditor,
setModels: (modelInfo: modelInfoType, model: editor.ITextModel, editorId: number) => void,
setModels: (
modelInfo: modelInfoType,
model: editor.ITextModel,
editorId: number,
id: string,
) => void,
setActiveModel: (modelId: string, model: editor.ITextModel, editorId: number) => void,
editorId: number,
) {
const modelUri = monaco.Uri.file(modelInfo.filename);
const modelUri = monaco.Uri.file(modelInfo.id);
const model =
monaco.editor.getModel(modelUri) ||
monaco.editor.createModel(modelInfo.value, modelInfo.language, modelUri);
// console.log(monaco.editor.getModel(modelUri));
setActiveModel(modelInfo.filename, model, editorId);
setModels(modelInfo, model, editorId);
setActiveModel(modelInfo.id, model, editorId);
setModels(modelInfo, model, editorId, modelInfo.id);
editor.setModel(model);
}
32 changes: 25 additions & 7 deletions src/components/file/fileItem/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ interface FileItemProps {

export const FileItem: React.FC<FileItemProps> = ({ file, onMouseupFn }: FileItemProps) => {
// used for editor
const { splitState } = useSplitStore();
const { editors } = useEditorStore();
const { splitState, removeSplit } = useSplitStore();
const { editors, removeEditor } = useEditorStore();
const { activeEditor, activeEditorId } = useActiveEditorStore();
const { monacos } = useMonacoStore();
const { setActiveModel } = useActiveModelStore();
const { models, setModels } = useModelsStore();
const { models, setModels, removeModel, removeAllModel } = useModelsStore();
const keepedEditorCount = splitState.filter((item) => item).length;
// used for dnd
const clickClient = useRef({
x: 0,
Expand Down Expand Up @@ -69,17 +70,17 @@ export const FileItem: React.FC<FileItemProps> = ({ file, onMouseupFn }: FileIte

const willChangeEditorId = activeEditor ? activeEditorId : splitState.findIndex((item) => item);

const mathModel = models.filter((model) => model.filename === file.filename);
const mathModel = models.filter((model) => model.id === file.id);
// console.log(splitState, mathModel[0], willChangeEditor, willChangeEditorId);

if (mathModel.length > 0) {
mathModel[0].model &&
setActiveModel(mathModel[0].filename, mathModel[0].model, willChangeEditorId);
mathModel[0].model && setActiveModel(mathModel[0].id, mathModel[0].model, willChangeEditorId);
mathModel[0].model &&
setModels(
{ filename: mathModel[0].filename, value: '', language: 'typescript' },
{ filename: mathModel[0].filename, value: '', language: 'typescript', id: file.id },
mathModel[0].model,
willChangeEditorId,
file.id,
);
willChangeEditor?.setModel(mathModel[0].model);
} else {
Expand Down Expand Up @@ -120,6 +121,23 @@ export const FileItem: React.FC<FileItemProps> = ({ file, onMouseupFn }: FileIte
onMouseUp={(e) => {
e.stopPropagation();
removeFileById(file.id);

editors.forEach((editor, editorId) => {
const newModels = removeModel(file.id, editorId);

if (newModels && newModels.filename) {
setActiveModel(newModels.filename, newModels.model, editorId);
editor && editor.setModel(newModels.model);
} else {
removeAllModel(editorId);
editor && editor.setModel(null);

if (keepedEditorCount > 1) {
removeEditor(editorId);
removeSplit(editorId);
}
}
});
}}
className=" w-[15px] pr-[-4px] h-[15px] text-white/70 hover:text-white hidden group-hover:block"
/>
Expand Down
24 changes: 15 additions & 9 deletions src/store/editorStore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,12 @@ export const useMonacoStore = create<MonacoState & MonacoAction>((set, get) => (
return get().monacos[index] || null;
},
}));

// filename 为model对应文件名,id为uuid
export type modelInfoType = {
filename: string;
language: string;
value: string;
id: string;
};

export type modelType = modelInfoType & { model: editor.ITextModel; usedBy: number[] };
Expand All @@ -81,8 +82,13 @@ interface ModelsState {
models: modelsType | [];
}
interface ModelsAction {
setModels: (modelInfo: modelInfoType, model: editor.ITextModel, editorId: number) => void;
removeModel: (filename: string, editorId: number) => any;
setModels: (
modelInfo: modelInfoType,
model: editor.ITextModel,
editorId: number,
id: string,
) => void;
removeModel: (id: string, editorId: number) => any;
removeAllModel: (editorId: number) => void;
}
export const useModelsStore = create<ModelsState & ModelsAction>((set, get) => ({
Expand All @@ -96,7 +102,7 @@ export const useModelsStore = create<ModelsState & ModelsAction>((set, get) => (
}

set((state) => {
const existingModelIndex = state.models.findIndex((m) => m.filename === modelInfo.filename);
const existingModelIndex = state.models.findIndex((m) => m.id === modelInfo.id);

if (existingModelIndex === -1) {
return {
Expand Down Expand Up @@ -124,21 +130,21 @@ export const useModelsStore = create<ModelsState & ModelsAction>((set, get) => (
});
},

removeModel: (filename: string, editorId: number) => {
removeModel: (id: string, editorId: number) => {
set((state) => {
const existingModelIndex = state.models.findIndex((m) => m.filename === filename);
const existingModelIndex = state.models.findIndex((m) => m.id === id);

if (existingModelIndex !== -1) {
const preModels = [...state.models];

if (preModels[existingModelIndex].usedBy.includes(editorId)) {
preModels[existingModelIndex].usedBy = preModels[existingModelIndex].usedBy.filter(
(id) => id !== editorId,
(eid) => eid !== editorId,
);

if (preModels[existingModelIndex].usedBy.length === 0) {
return {
models: [...preModels.filter((model) => model.filename !== filename)],
models: [...preModels.filter((model) => model.id !== id)],
};
} else {
return {
Expand Down Expand Up @@ -183,6 +189,7 @@ export const useModelsStore = create<ModelsState & ModelsAction>((set, get) => (
},
}));

// modelId原为model对应文件名,为满足打开多个同名文件修改为对应文件的uuid
interface activeModelState {
activeMap: { modelId: string; model: editor.ITextModel | null }[];
}
Expand All @@ -194,7 +201,6 @@ interface activeModelAction {

export const useActiveModelStore = create<activeModelState & activeModelAction>((set) => ({
activeMap: [],

setActiveModel: (modelId: string, model: editor.ITextModel, editorId: number) =>
set((state) => {
const preActiveMap = [...state.activeMap];
Expand Down

0 comments on commit 4a97823

Please sign in to comment.