Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow edit same name file #66

Merged
merged 5 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading