fix: big add file and folder logic
This commit is contained in:
@ -170,7 +170,7 @@ function RenameForm({
|
||||
autoCapitalize="off"
|
||||
autoCorrect="off"
|
||||
placeholder={row.name}
|
||||
className="w-full py-1 bg-transparent text-chalkboard-100 placeholder:text-chalkboard-70 dark:text-chalkboard-10 dark:placeholder:text-chalkboard-50 focus:outline-none focus:ring-0"
|
||||
className="overflow-hidden whitespace-nowrap text-ellipsis py-1 bg-transparent text-chalkboard-100 placeholder:text-chalkboard-70 dark:text-chalkboard-10 dark:placeholder:text-chalkboard-50 focus:outline-none focus:ring-0"
|
||||
onKeyDown={handleKeyDown}
|
||||
onBlur={onSubmit}
|
||||
/>
|
||||
@ -247,7 +247,7 @@ export const FileExplorerRowElement = ({
|
||||
name={row.icon}
|
||||
className="inline-block w-4 text-current mr-1"
|
||||
/>
|
||||
{!isMyRowRenaming ? (
|
||||
{!isMyRowRenaming && !row.isFake ? (
|
||||
<span className="overflow-hidden whitespace-nowrap text-ellipsis">
|
||||
{row.name}
|
||||
</span>
|
||||
|
||||
@ -9,10 +9,12 @@ import {
|
||||
CONTAINER_IS_SELECTED,
|
||||
STARTING_INDEX_TO_SELECT,
|
||||
FILE_PLACEHOLDER_NAME,
|
||||
FOLDER_PLACEHOLDER_NAME
|
||||
FOLDER_PLACEHOLDER_NAME,
|
||||
} from '@src/components/Explorer/utils'
|
||||
import type {
|
||||
FileExplorerEntry,
|
||||
FileExplorerRow,
|
||||
} from '@src/components/Explorer/utils'
|
||||
import type { FileExplorerEntry,
|
||||
FileExplorerRow } from '@src/components/Explorer/utils'
|
||||
import { FileExplorerHeaderActions } from '@src/components/Explorer/FileExplorerHeaderActions'
|
||||
import { useState, useRef, useEffect } from 'react'
|
||||
import { systemIOActor } from '@src/lib/singletons'
|
||||
@ -20,7 +22,9 @@ import { SystemIOMachineEvents } from '@src/machines/systemIO/utils'
|
||||
import { sortFilesAndDirectories } from '@src/lib/desktopFS'
|
||||
import {
|
||||
alwaysEndFileWithEXT,
|
||||
desktopSafePathSplit,
|
||||
getEXTWithPeriod,
|
||||
getParentAbsolutePath,
|
||||
joinOSPaths,
|
||||
} from '@src/lib/paths'
|
||||
import { useProjectDirectoryPath } from '@src/machines/systemIO/hooks'
|
||||
@ -191,6 +195,7 @@ export const ProjectExplorer = ({
|
||||
// TODO: Implement renameFolder and renameFile to navigate
|
||||
setIsRenaming(false)
|
||||
isRenamingRef.current = false
|
||||
setFakeRow(null)
|
||||
|
||||
if (!event) {
|
||||
return
|
||||
@ -205,28 +210,37 @@ export const ProjectExplorer = ({
|
||||
// Rename a folder
|
||||
if (row.isFolder) {
|
||||
if (requestedName !== name) {
|
||||
systemIOActor.send({
|
||||
type: SystemIOMachineEvents.renameFolder,
|
||||
data: {
|
||||
requestedFolderName: requestedName,
|
||||
folderName: name,
|
||||
absolutePathToParentDirectory: joinOSPaths(
|
||||
projectDirectoryPath,
|
||||
child.parentPath
|
||||
),
|
||||
},
|
||||
})
|
||||
// TODO: Gotcha... Set new string open even if it fails?
|
||||
if (openedRowsRef.current[child.key]) {
|
||||
// If the file tree had the folder opened make the new one open.
|
||||
const newOpenedRows = { ...openedRowsRef.current }
|
||||
const key = constructPath({
|
||||
parentPath: child.parentPath,
|
||||
name: requestedName,
|
||||
if (row.isFake) {
|
||||
// create
|
||||
systemIOActor.send({
|
||||
type: SystemIOMachineEvents.createBlankFolder,
|
||||
data: {
|
||||
requestedAbsolutePath: joinOSPaths(getParentAbsolutePath(row.path), requestedName)
|
||||
},
|
||||
})
|
||||
newOpenedRows[key] = true
|
||||
setOpenedRows(newOpenedRows)
|
||||
} else {
|
||||
// rename
|
||||
systemIOActor.send({
|
||||
type: SystemIOMachineEvents.renameFolder,
|
||||
data: {
|
||||
requestedFolderName: requestedName,
|
||||
folderName: name,
|
||||
absolutePathToParentDirectory: getParentAbsolutePath(row.path)
|
||||
},
|
||||
})
|
||||
// TODO: Gotcha... Set new string open even if it fails?
|
||||
if (openedRowsRef.current[child.key]) {
|
||||
// If the file tree had the folder opened make the new one open.
|
||||
const newOpenedRows = { ...openedRowsRef.current }
|
||||
const key = constructPath({
|
||||
parentPath: child.parentPath,
|
||||
name: requestedName,
|
||||
})
|
||||
newOpenedRows[key] = true
|
||||
setOpenedRows(newOpenedRows)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
// rename a file
|
||||
@ -239,21 +253,29 @@ export const ProjectExplorer = ({
|
||||
// TODO: OH NO!
|
||||
return
|
||||
}
|
||||
systemIOActor.send({
|
||||
|
||||
// create a file if it is fake
|
||||
if (row.isFake) {
|
||||
systemIOActor.send({
|
||||
type: SystemIOMachineEvents.createBlankFile,
|
||||
data: {
|
||||
requestedAbsolutePath: joinOSPaths(getParentAbsolutePath(row.path),fileNameForcedWithOriginalExt)
|
||||
},
|
||||
})
|
||||
} else {
|
||||
// rename the file otherwise
|
||||
systemIOActor.send({
|
||||
type: SystemIOMachineEvents.renameFile,
|
||||
data: {
|
||||
requestedFileNameWithExtension: fileNameForcedWithOriginalExt,
|
||||
fileNameWithExtension: name,
|
||||
absolutePathToParentDirectory: joinOSPaths(
|
||||
projectDirectoryPath,
|
||||
child.parentPath
|
||||
),
|
||||
absolutePathToParentDirectory: getParentAbsolutePath(row.path)
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
return row
|
||||
}) || []
|
||||
|
||||
@ -261,16 +283,39 @@ export const ProjectExplorer = ({
|
||||
let showPlaceHolder = false
|
||||
if (fakeRow?.isFile) {
|
||||
// fake row is a file
|
||||
const showFileAtSameLevel = fakeRow?.entry?.parentPath === row.parentPath && !row.isFolder === (fakeRow?.entry?.children === null) && row.name === FILE_PLACEHOLDER_NAME
|
||||
const showFileWithinFolder = !row.isFolder && !!fakeRow?.entry?.children && fakeRow?.entry?.key === row.parentPath
|
||||
showPlaceHolder = showFileAtSameLevel || showFileWithinFolder
|
||||
} else {
|
||||
const showFileAtSameLevel =
|
||||
fakeRow?.entry?.parentPath === row.parentPath &&
|
||||
!row.isFolder === (fakeRow?.entry?.children === null) &&
|
||||
row.name === FILE_PLACEHOLDER_NAME
|
||||
const showFileWithinFolder =
|
||||
!row.isFolder &&
|
||||
!!fakeRow?.entry?.children &&
|
||||
fakeRow?.entry?.key === row.parentPath &&
|
||||
row.name === FILE_PLACEHOLDER_NAME
|
||||
const fakeRowIsNullShowRootFile = fakeRow.entry === null && row.parentPath === project.name &&
|
||||
row.name === FILE_PLACEHOLDER_NAME
|
||||
showPlaceHolder = showFileAtSameLevel || showFileWithinFolder || fakeRowIsNullShowRootFile
|
||||
} else if (fakeRow?.isFile === false){
|
||||
// fake row is a folder
|
||||
const showFolderAtSameLevel = fakeRow?.entry?.parentPath === row.parentPath && !row.isFolder === (!!fakeRow?.entry?.children) && row.name === FOLDER_PLACEHOLDER_NAME
|
||||
const showFolderWithinFolder = row.isFolder && !!fakeRow?.entry?.children && fakeRow?.entry?.key === row.parentPath
|
||||
showPlaceHolder = showFolderAtSameLevel || showFolderWithinFolder
|
||||
const showFolderAtSameLevel =
|
||||
fakeRow?.entry?.parentPath === row.parentPath &&
|
||||
!row.isFolder === !!fakeRow?.entry?.children &&
|
||||
row.name === FOLDER_PLACEHOLDER_NAME
|
||||
const showFolderWithinFolder =
|
||||
row.isFolder &&
|
||||
!!fakeRow?.entry?.children &&
|
||||
fakeRow?.entry?.key === row.parentPath &&
|
||||
row.name === FOLDER_PLACEHOLDER_NAME
|
||||
const fakeRowIsNullShowRootFolder = fakeRow.entry === null && row.parentPath === project.name &&
|
||||
row.name === FOLDER_PLACEHOLDER_NAME
|
||||
showPlaceHolder = showFolderAtSameLevel || showFolderWithinFolder || fakeRowIsNullShowRootFolder
|
||||
}
|
||||
const skipPlaceHolder = !(row.name === FILE_PLACEHOLDER_NAME || row.name === FOLDER_PLACEHOLDER_NAME) || showPlaceHolder
|
||||
const skipPlaceHolder =
|
||||
!(
|
||||
row.name === FILE_PLACEHOLDER_NAME ||
|
||||
row.name === FOLDER_PLACEHOLDER_NAME
|
||||
) || showPlaceHolder
|
||||
row.isFake = showPlaceHolder
|
||||
return row.render && skipPlaceHolder
|
||||
})
|
||||
|
||||
|
||||
@ -130,26 +130,32 @@ export const flattenProject = (
|
||||
return flattenTreeInOrder
|
||||
}
|
||||
|
||||
export const addPlaceHoldersForNewFileAndFolder = (children: FileEntry[] | null, parentPath: string) => {
|
||||
export const addPlaceHoldersForNewFileAndFolder = (
|
||||
children: FileEntry[] | null,
|
||||
parentPath: string
|
||||
) => {
|
||||
if (children === null) {
|
||||
return
|
||||
}
|
||||
|
||||
for( let i = 0; i < children.length; i++) {
|
||||
addPlaceHoldersForNewFileAndFolder(children[i].children, joinOSPaths(parentPath, children[i].name))
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
addPlaceHoldersForNewFileAndFolder(
|
||||
children[i].children,
|
||||
joinOSPaths(parentPath, children[i].name)
|
||||
)
|
||||
}
|
||||
|
||||
const placeHolderFolderEntry : FileEntry = {
|
||||
|
||||
const placeHolderFolderEntry: FileEntry = {
|
||||
path: joinOSPaths(parentPath, FOLDER_PLACEHOLDER_NAME),
|
||||
name: FOLDER_PLACEHOLDER_NAME,
|
||||
children: []
|
||||
children: [],
|
||||
}
|
||||
children.unshift(placeHolderFolderEntry)
|
||||
|
||||
const placeHolderFileEntry : FileEntry = {
|
||||
const placeHolderFileEntry: FileEntry = {
|
||||
path: joinOSPaths(parentPath, FILE_PLACEHOLDER_NAME),
|
||||
name: FILE_PLACEHOLDER_NAME,
|
||||
children: null
|
||||
children: null,
|
||||
}
|
||||
children.push(placeHolderFileEntry)
|
||||
}
|
||||
@ -159,4 +165,4 @@ export const NOTHING_IS_SELECTED: number = -2
|
||||
export const CONTAINER_IS_SELECTED: number = -1
|
||||
export const STARTING_INDEX_TO_SELECT: number = 0
|
||||
export const FOLDER_PLACEHOLDER_NAME = '.zoo-placeholder-folder'
|
||||
export const FILE_PLACEHOLDER_NAME = '.zoo-placeholder-file'
|
||||
export const FILE_PLACEHOLDER_NAME = '.zoo-placeholder-file.kcl'
|
||||
|
||||
@ -245,3 +245,10 @@ export const getEXTWithPeriod = (filePath: string) => {
|
||||
}
|
||||
return extension
|
||||
}
|
||||
|
||||
export const getParentAbsolutePath = (absolutePath: string) => {
|
||||
const split = desktopSafePathSplit(absolutePath)
|
||||
split.pop()
|
||||
const joined = desktopSafePathJoin(split)
|
||||
return joined
|
||||
}
|
||||
@ -162,7 +162,19 @@ export const systemIOMachine = setup({
|
||||
data: {
|
||||
requestedPath: string
|
||||
}
|
||||
},
|
||||
}
|
||||
| {
|
||||
type: SystemIOMachineEvents.createBlankFile
|
||||
data: {
|
||||
requestedAbsolutePath: string
|
||||
}
|
||||
}
|
||||
| {
|
||||
type: SystemIOMachineEvents.createBlankFolder
|
||||
data: {
|
||||
requestedAbsolutePath: string
|
||||
}
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
[SystemIOMachineActions.setFolders]: assign({
|
||||
@ -442,6 +454,38 @@ export const systemIOMachine = setup({
|
||||
}
|
||||
}
|
||||
),
|
||||
[SystemIOMachineActors.createBlankFile]: fromPromise(
|
||||
async ({
|
||||
input,
|
||||
}: {
|
||||
input: {
|
||||
context: SystemIOContext
|
||||
rootContext: AppMachineContext
|
||||
requestedAbsolutePath: string
|
||||
}
|
||||
}) => {
|
||||
return {
|
||||
message: '',
|
||||
requestedAbsolutePath: '',
|
||||
}
|
||||
}
|
||||
),
|
||||
[SystemIOMachineActors.createBlankFolder]: fromPromise(
|
||||
async ({
|
||||
input,
|
||||
}: {
|
||||
input: {
|
||||
context: SystemIOContext
|
||||
rootContext: AppMachineContext
|
||||
requestedAbsolutePath: string
|
||||
}
|
||||
}) => {
|
||||
return {
|
||||
message: '',
|
||||
requestedAbsolutePath: '',
|
||||
}
|
||||
}
|
||||
),
|
||||
},
|
||||
}).createMachine({
|
||||
initial: SystemIOMachineStates.idle,
|
||||
@ -529,6 +573,12 @@ export const systemIOMachine = setup({
|
||||
[SystemIOMachineEvents.deleteFileOrFolder]: {
|
||||
target: SystemIOMachineStates.deletingFileOrFolder,
|
||||
},
|
||||
[SystemIOMachineEvents.createBlankFile]: {
|
||||
target: SystemIOMachineStates.creatingBlankFile,
|
||||
},
|
||||
[SystemIOMachineEvents.createBlankFolder]: {
|
||||
target: SystemIOMachineStates.creatingBlankFolder,
|
||||
},
|
||||
},
|
||||
},
|
||||
[SystemIOMachineStates.readingFolders]: {
|
||||
@ -919,5 +969,49 @@ export const systemIOMachine = setup({
|
||||
},
|
||||
},
|
||||
},
|
||||
[SystemIOMachineStates.creatingBlankFile]: {
|
||||
invoke: {
|
||||
id: SystemIOMachineActors.createBlankFile,
|
||||
src: SystemIOMachineActors.createBlankFile,
|
||||
input: ({ context, event, self }) => {
|
||||
assertEvent(event, SystemIOMachineEvents.createBlankFile)
|
||||
return {
|
||||
context,
|
||||
requestedAbsolutePath: event.data.requestedAbsolutePath,
|
||||
rootContext: self.system.get('root').getSnapshot().context,
|
||||
}
|
||||
},
|
||||
onDone: {
|
||||
target: SystemIOMachineStates.readingFolders,
|
||||
actions: [SystemIOMachineActions.toastSuccess],
|
||||
},
|
||||
onError: {
|
||||
target: SystemIOMachineStates.idle,
|
||||
actions: [SystemIOMachineActions.toastError],
|
||||
},
|
||||
},
|
||||
},
|
||||
[SystemIOMachineStates.creatingBlankFolder]: {
|
||||
invoke: {
|
||||
id: SystemIOMachineActors.createBlankFolder,
|
||||
src: SystemIOMachineActors.createBlankFolder,
|
||||
input: ({ context, event, self }) => {
|
||||
assertEvent(event, SystemIOMachineEvents.createBlankFolder)
|
||||
return {
|
||||
context,
|
||||
requestedAbsolutePath: event.data.requestedAbsolutePath,
|
||||
rootContext: self.system.get('root').getSnapshot().context,
|
||||
}
|
||||
},
|
||||
onDone: {
|
||||
target: SystemIOMachineStates.readingFolders,
|
||||
actions: [SystemIOMachineActions.toastSuccess],
|
||||
},
|
||||
onError: {
|
||||
target: SystemIOMachineStates.idle,
|
||||
actions: [SystemIOMachineActions.toastError],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@ -270,12 +270,18 @@ export const systemIOMachineDesktop = systemIOMachine.provide({
|
||||
const configuration = await readAppSettingsFile()
|
||||
|
||||
// Create the project around the file if newProject
|
||||
await createNewProjectDirectory(
|
||||
try {
|
||||
const result = await createNewProjectDirectory(
|
||||
newProjectName,
|
||||
requestedCode,
|
||||
configuration,
|
||||
newFileName
|
||||
)
|
||||
)
|
||||
console.log(result)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
message: 'File created successfully',
|
||||
@ -526,5 +532,55 @@ export const systemIOMachineDesktop = systemIOMachine.provide({
|
||||
}
|
||||
}
|
||||
),
|
||||
[SystemIOMachineActors.createBlankFile]: fromPromise(
|
||||
async ({
|
||||
input,
|
||||
}: {
|
||||
input: {
|
||||
context: SystemIOContext
|
||||
rootContext: AppMachineContext
|
||||
requestedAbsolutePath: string
|
||||
}
|
||||
}) => {
|
||||
try {
|
||||
const result = await window.electron.stat(input.requestedAbsolutePath)
|
||||
if (result) {
|
||||
return Promise.reject(new Error(`File ${input.requestedAbsolutePath} already exists`))
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
await window.electron.writeFile(input.requestedAbsolutePath, '')
|
||||
return {
|
||||
message: `File ${input.requestedAbsolutePath} written successfully`,
|
||||
requestedAbsolutePath: input.requestedAbsolutePath,
|
||||
}
|
||||
}
|
||||
),
|
||||
[SystemIOMachineActors.createBlankFolder]: fromPromise(
|
||||
async ({
|
||||
input,
|
||||
}: {
|
||||
input: {
|
||||
context: SystemIOContext
|
||||
rootContext: AppMachineContext
|
||||
requestedAbsolutePath: string
|
||||
}
|
||||
}) => {
|
||||
try {
|
||||
const result = await window.electron.stat(input.requestedAbsolutePath)
|
||||
if (result) {
|
||||
return Promise.reject(new Error(`Folder ${input.requestedAbsolutePath} already exists`))
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
await window.electron.mkdir(input.requestedAbsolutePath, {recursive: true})
|
||||
return {
|
||||
message: `File ${input.requestedAbsolutePath} written successfully`,
|
||||
requestedAbsolutePath: input.requestedAbsolutePath,
|
||||
}
|
||||
}
|
||||
),
|
||||
},
|
||||
})
|
||||
|
||||
@ -19,6 +19,8 @@ export enum SystemIOMachineActors {
|
||||
renameFolder = 'renameFolder',
|
||||
renameFile = 'renameFile',
|
||||
deleteFileOrFolder = 'deleteFileOrFolder',
|
||||
createBlankFile = 'create blank file',
|
||||
createBlankFolder = 'create blank folder'
|
||||
}
|
||||
|
||||
export enum SystemIOMachineStates {
|
||||
@ -39,6 +41,8 @@ export enum SystemIOMachineStates {
|
||||
renamingFolder = 'renamingFolder',
|
||||
renamingFile = 'renamingFile',
|
||||
deletingFileOrFolder = 'deletingFileOrFolder',
|
||||
creatingBlankFile = 'creatingBlankFile',
|
||||
creatingBlankFolder = 'creatingBlankFolder'
|
||||
}
|
||||
|
||||
const donePrefix = 'xstate.done.actor.'
|
||||
@ -70,6 +74,8 @@ export enum SystemIOMachineEvents {
|
||||
renameFolder = 'rename folder',
|
||||
renameFile = 'rename file',
|
||||
deleteFileOrFolder = 'delete file or folder',
|
||||
createBlankFile = 'create blank file',
|
||||
createBlankFolder = 'create blank folder'
|
||||
}
|
||||
|
||||
export enum SystemIOMachineActions {
|
||||
|
||||
Reference in New Issue
Block a user