diff --git a/src/components/Providers/SystemIOProviderDesktop.tsx b/src/components/Providers/SystemIOProviderDesktop.tsx index fa7b11696..45c041158 100644 --- a/src/components/Providers/SystemIOProviderDesktop.tsx +++ b/src/components/Providers/SystemIOProviderDesktop.tsx @@ -13,7 +13,7 @@ export const useProjectDirectoryPath = () => export function SystemIOMachineLogicListener() { const requestedProjectName = useRequestedProjectName() const requestedFileName = useRequestedFileName() - console.log(requestedFileName,'okay') + console.log(requestedFileName, 'okay') const projectDirectoryPath = useProjectDirectoryPath() const navigate = useNavigate() @@ -42,10 +42,7 @@ export function SystemIOMachineLogicListener() { projectDirectoryPath, requestedFileName.project ) - const filePath = window.electron.join( - projectPath, - requestedFileName.file - ) + const filePath = window.electron.join(projectPath, requestedFileName.file) const requestedPath = `${PATHS.FILE}/${encodeURIComponent(filePath)}` navigate(requestedPath) }, [requestedFileName]) diff --git a/src/machines/systemIO/systemIOMachine.ts b/src/machines/systemIO/systemIOMachine.ts index 9bb5ddcc0..471bc40b5 100644 --- a/src/machines/systemIO/systemIOMachine.ts +++ b/src/machines/systemIO/systemIOMachine.ts @@ -36,10 +36,18 @@ export const systemIOMachine = setup({ | { type: SystemIOMachineEvents.navigateToProject data: { requestedProjectName: string } - } + } | { type: SystemIOMachineEvents.navigateToFile - data: { requestedProjectName: string, requestedFileName: string } + data: { requestedProjectName: string; requestedFileName: string } + } + | { + type: SystemIOMachineEvents.createProject + data: { requestedProjectName: string } + } + | { + type: SystemIOMachineEvents.renameProject + data: { requestedProjectName: string, projectName: string } } }, actions: { @@ -67,7 +75,10 @@ export const systemIOMachine = setup({ [SystemIOMachineActions.setRequestedFileName]: assign({ requestedFileName: ({ event }) => { assertEvent(event, SystemIOMachineEvents.navigateToFile) - return { project: event.data.requestedProjectName, file: event.data.requestedFileName } + return { + project: event.data.requestedProjectName, + file: event.data.requestedFileName, + } }, }), }, @@ -77,6 +88,13 @@ export const systemIOMachine = setup({ return [] } ), + [SystemIOMachineActors.createProject]: fromPromise( + async ({ + input: context, + }: { + input: { context: SystemIOContext; requestProjectName: string } + }) => {} + ), }, }).createMachine({ initial: SystemIOMachineStates.idle, @@ -89,14 +107,17 @@ export const systemIOMachine = setup({ projectDirectoryPath: NO_PROJECT_DIRECTORY, hasListedProjects: false, requestedProjectName: { name: NO_PROJECT_DIRECTORY }, - requestedFileName: { name: NO_PROJECT_DIRECTORY }, + requestedFileName: { + project: NO_PROJECT_DIRECTORY, + file: NO_PROJECT_DIRECTORY, + }, }), states: { [SystemIOMachineStates.idle]: { on: { // on can be an action [SystemIOMachineEvents.readFoldersFromProjectDirectory]: - SystemIOMachineStates.readingFolders, + SystemIOMachineStates.readingFolders, [SystemIOMachineEvents.setProjectDirectoryPath]: { target: SystemIOMachineStates.readingFolders, actions: [SystemIOMachineActions.setProjectDirectoryPath], @@ -107,6 +128,12 @@ export const systemIOMachine = setup({ [SystemIOMachineEvents.navigateToFile]: { actions: [SystemIOMachineActions.setRequestedFileName], }, + [SystemIOMachineEvents.createProject]: { + target: SystemIOMachineStates.creatingProject, + }, + [SystemIOMachineEvents.renameProject]: { + target: SystemIOMachineStates.renamingProject, + }, }, }, [SystemIOMachineStates.readingFolders]: { @@ -125,6 +152,45 @@ export const systemIOMachine = setup({ }, }, }, + [SystemIOMachineStates.creatingProject]: { + invoke: { + id: SystemIOMachineActors.createProject, + src: SystemIOMachineActors.createProject, + input: ({ context, event }) => { + assertEvent(event, SystemIOMachineEvents.createProject) + return { + context, + requestedProjectName: event.data.requestedProjectName, + } + }, + onDone: { + target: SystemIOMachineStates.readingFolders, + }, + onError: { + target: SystemIOMachineStates.idle, + }, + }, + }, + [SystemIOMachineStates.renamingProject]: { + invoke: { + id: SystemIOMachineActors.renameProject, + src: SystemIOMachineActors.renameProject, + input: ({ context, event }) => { + assertEvent(event, SystemIOMachineEvents.renameProject) + return { + context, + requestedProjectName: event.data.requestedProjectName, + projectName: event.data.projectName + } + }, + onDone: { + target: SystemIOMachineStates.readingFolders, + }, + onError: { + target: SystemIOMachineStates.idle, + }, + }, + }, }, }) diff --git a/src/machines/systemIO/systemIOMachineDesktop.ts b/src/machines/systemIO/systemIOMachineDesktop.ts index 2913b6402..61abcd95a 100644 --- a/src/machines/systemIO/systemIOMachineDesktop.ts +++ b/src/machines/systemIO/systemIOMachineDesktop.ts @@ -1,4 +1,10 @@ -import { getProjectInfo, mkdirOrNOOP } from '@src/lib/desktop' +import { + createNewProjectDirectory, + getProjectInfo, + mkdirOrNOOP, + renameProjectDirectory +} from '@src/lib/desktop' +import { getUniqueProjectName, doesProjectNameNeedInterpolated, getNextProjectIndex, interpolateProjectNameWithIndex } from '@src/lib/desktopFS' import type { Project } from '@src/lib/project' import { systemIOMachine } from '@src/machines/systemIO/systemIOMachine' import type { SystemIOContext } from '@src/machines/systemIO/utils' @@ -53,5 +59,46 @@ export const systemIOMachineDesktop = systemIOMachine.provide({ return projects } ), + [SystemIOMachineActors.createProject]: fromPromise( + async ({ + input, + }: { + input: { context: SystemIOContext; requestedProjectName: string } + }) => { + const folders = input.context.folders + const requestedProjectName = input.requestedProjectName + const uniqueName = getUniqueProjectName(requestedProjectName, folders) + await createNewProjectDirectory(uniqueName) + } + ), + [SystemIOMachineActors.renameProject]: fromPromise( + async ({ + input, + }: { + input: { context: SystemIOContext; requestedProjectName: string, projectName: string } + }) => { + const folders = input.context.folders + const requestedProjectName = input.requestedProjectName + const projectName = input.projectName + let newProjectName : string = requestedProjectName + if (doesProjectNameNeedInterpolated(requestedProjectName)) { + const nextIndex = getNextProjectIndex(requestedProjectName, folders) + newProjectName = interpolateProjectNameWithIndex(requestedProjectName, nextIndex) + } + + // Toast an error if the project name is taken + if (folders.find((p) => p.name === name)) { + return Promise.reject( + new Error(`Project with name "${name}" already exists`) + ) + } + + await renameProjectDirectory( + window.electron.path.join(input.context.projectDirectoryPath, projectName), + newProjectName + ) + // DONE + } + ), }, }) diff --git a/src/machines/systemIO/utils.ts b/src/machines/systemIO/utils.ts index 4310e8742..d771c46f5 100644 --- a/src/machines/systemIO/utils.ts +++ b/src/machines/systemIO/utils.ts @@ -3,12 +3,16 @@ import type { Project } from '@src/lib/project' export enum SystemIOMachineActors { readFoldersFromProjectDirectory = 'read folders from project directory', setProjectDirectoryPath = 'set project directory path', + createProject = 'create project', + renameProject = 'rename project' } export enum SystemIOMachineStates { idle = 'idle', readingFolders = 'readingFolders', settingProjectDirectoryPath = 'settingProjectDirectoryPath', + creatingProject = 'creatingProject', + renamingProject = 'renamingProject' } const donePrefix = 'xstate.done.actor.' @@ -19,7 +23,9 @@ export enum SystemIOMachineEvents { 'read folders from project directory', setProjectDirectoryPath = 'set project directory path', navigateToProject = 'navigate to project', - navigateToFile = 'navigate to file' + navigateToFile = 'navigate to file', + createProject = 'create project', + renameProject = 'rename project' } export enum SystemIOMachineActions { @@ -43,5 +49,5 @@ export type SystemIOContext = { // this is required to prevent chokidar from spamming invalid events during initialization. hasListedProjects: boolean requestedProjectName: { name: string } - requestedFileName: {project: string, file: string} + requestedFileName: { project: string; file: string } }