This commit is contained in:
Pierre Jacquier
2024-02-22 05:39:48 -05:00
parent 0772f986c9
commit 7f03c33bfb
10 changed files with 29 additions and 39 deletions

View File

@ -40,9 +40,9 @@ import * as Sentry from '@sentry/react'
import ModelingMachineProvider from 'components/ModelingMachineProvider' import ModelingMachineProvider from 'components/ModelingMachineProvider'
import { KclContextProvider, kclManager } from 'lang/KclSingleton' import { KclContextProvider, kclManager } from 'lang/KclSingleton'
import FileMachineProvider from 'components/FileMachineProvider' import FileMachineProvider from 'components/FileMachineProvider'
import { sep } from '@tauri-apps/api/path' import { join, sep } from '@tauri-apps/api/path'
import { paths } from 'lib/paths' import { paths } from 'lib/paths'
import { IndexLoaderData, HomeLoaderData, FileEntry } from 'lib/types' import type { IndexLoaderData, HomeLoaderData, FileEntry } from 'lib/types'
import { fileSystemManager } from 'lang/std/fileSystemManager' import { fileSystemManager } from 'lang/std/fileSystemManager'
import { invoke } from '@tauri-apps/api/core' import { invoke } from '@tauri-apps/api/core'
@ -157,20 +157,20 @@ const router = createBrowserRouter(
const projectAndFile = decodedId.replace(defaultDir + sep(), '') const projectAndFile = decodedId.replace(defaultDir + sep(), '')
const firstSlashIndex = projectAndFile.indexOf(sep()) const firstSlashIndex = projectAndFile.indexOf(sep())
const projectName = projectAndFile.slice(0, firstSlashIndex) const projectName = projectAndFile.slice(0, firstSlashIndex)
const projectPath = defaultDir + sep() + projectName const projectPath = await join(defaultDir, projectName)
const currentFileName = projectAndFile.slice(firstSlashIndex + 1) const currentFileName = projectAndFile.slice(firstSlashIndex + 1)
if (firstSlashIndex === -1 || !currentFileName) if (firstSlashIndex === -1 || !currentFileName)
return redirect( return redirect(
`${paths.FILE}/${encodeURIComponent( `${paths.FILE}/${encodeURIComponent(
`${params.id}${sep()}${PROJECT_ENTRYPOINT}` await join(params.id, PROJECT_ENTRYPOINT)
)}` )}`
) )
// Note that PROJECT_ENTRYPOINT is hardcoded until we support multiple files // Note that PROJECT_ENTRYPOINT is hardcoded until we support multiple files
const code = await readTextFile(decodedId) const code = await readTextFile(decodedId)
const entrypointMetadata = await stat( const entrypointMetadata = await stat(
projectPath + sep() + PROJECT_ENTRYPOINT await join(projectPath, PROJECT_ENTRYPOINT)
) )
const children = await invoke<FileEntry[]>('read_dir_recursive', { const children = await invoke<FileEntry[]>('read_dir_recursive', {
path: projectPath, path: projectPath,

View File

@ -17,7 +17,7 @@ import { DEFAULT_FILE_NAME, fileMachine } from 'machines/fileMachine'
import { mkdir, remove, rename, create } from '@tauri-apps/plugin-fs' import { mkdir, remove, rename, create } from '@tauri-apps/plugin-fs'
import { FILE_EXT, readProject } from 'lib/tauriFS' import { FILE_EXT, readProject } from 'lib/tauriFS'
import { isTauri } from 'lib/isTauri' import { isTauri } from 'lib/isTauri'
import { sep } from '@tauri-apps/api/path' import { join, sep } from '@tauri-apps/api/path'
type MachineContext<T extends AnyStateMachine> = { type MachineContext<T extends AnyStateMachine> = {
state: StateFrom<T> state: StateFrom<T>
@ -78,7 +78,7 @@ export const FileMachineProvider = ({
let name = event.data.name.trim() || DEFAULT_FILE_NAME let name = event.data.name.trim() || DEFAULT_FILE_NAME
if (event.data.makeDir) { if (event.data.makeDir) {
await mkdir(context.selectedDirectory.path + sep() + name) await mkdir(await join(context.selectedDirectory.path, name))
} else { } else {
await create( await create(
context.selectedDirectory.path + context.selectedDirectory.path +
@ -98,10 +98,8 @@ export const FileMachineProvider = ({
let name = newName ? newName : DEFAULT_FILE_NAME let name = newName ? newName : DEFAULT_FILE_NAME
await rename( await rename(
context.selectedDirectory.path + sep() + oldName, await join(context.selectedDirectory.path, oldName),
context.selectedDirectory.path + (await join(context.selectedDirectory.path, name)) +
sep() +
name +
(name.endsWith(FILE_EXT) || isDir ? '' : FILE_EXT), (name.endsWith(FILE_EXT) || isDir ? '' : FILE_EXT),
{} {}
) )

View File

@ -1,4 +1,4 @@
import { FileEntry, type IndexLoaderData } from 'lib/types' import type { FileEntry, IndexLoaderData } from 'lib/types'
import { paths } from 'lib/paths' import { paths } from 'lib/paths'
import { ActionButton } from './ActionButton' import { ActionButton } from './ActionButton'
import Tooltip from './Tooltip' import Tooltip from './Tooltip'

View File

@ -25,6 +25,7 @@ export async function exportSave(data: ArrayBuffer) {
} }
// Write the file. // Write the file.
// TODO: check if this is still value with the uint8 instance
await writeFile(filePath, new Uint8Array(file.contents)) await writeFile(filePath, new Uint8Array(file.contents))
} else { } else {
// Download the file to the user's computer. // Download the file to the user's computer.

View File

@ -6,7 +6,7 @@ import {
interpolateProjectNameWithIndex, interpolateProjectNameWithIndex,
isRelevantFileOrDir, isRelevantFileOrDir,
} from './tauriFS' } from './tauriFS'
import { FileEntry } from './types' import type { FileEntry } from './types'
describe('Test project name utility functions', () => { describe('Test project name utility functions', () => {
it('interpolates a project name without an index', () => { it('interpolates a project name without an index', () => {

View File

@ -1,14 +1,8 @@
import { import { mkdir, exists, writeTextFile, stat } from '@tauri-apps/plugin-fs'
mkdir,
exists,
readDir,
writeTextFile,
stat,
} from '@tauri-apps/plugin-fs'
import { invoke } from '@tauri-apps/api/core' import { invoke } from '@tauri-apps/api/core'
import { documentDir, homeDir, join, sep } from '@tauri-apps/api/path' import { documentDir, homeDir, join, sep } from '@tauri-apps/api/path'
import { isTauri } from './isTauri' import { isTauri } from './isTauri'
import { FileEntry, type ProjectWithEntryPointMetadata } from 'lib/types' import type { FileEntry, ProjectWithEntryPointMetadata } from 'lib/types'
const PROJECT_FOLDER = 'zoo-modeling-app-projects' const PROJECT_FOLDER = 'zoo-modeling-app-projects'
export const FILE_EXT = '.kcl' export const FILE_EXT = '.kcl'
@ -38,10 +32,10 @@ export async function initializeProjectDirectory(directory: string) {
docDirectory = await documentDir() docDirectory = await documentDir()
} catch (e) { } catch (e) {
console.log('error', e) console.log('error', e)
docDirectory = `${await homeDir()}Documents` // for headless Linux (eg. Github Actions) docDirectory = await join(await homeDir(), 'Documents') // for headless Linux (eg. Github Actions)
} }
const INITIAL_DEFAULT_DIR = docDirectory + sep() + PROJECT_FOLDER const INITIAL_DEFAULT_DIR = await join(docDirectory, PROJECT_FOLDER)
const defaultDirExists = await exists(INITIAL_DEFAULT_DIR) const defaultDirExists = await exists(INITIAL_DEFAULT_DIR)
@ -65,7 +59,6 @@ export async function getProjectsInDir(projectDir: string) {
const readProjects = ( const readProjects = (
await invoke<FileEntry[]>('read_dir_recursive', { path: projectDir }) await invoke<FileEntry[]>('read_dir_recursive', { path: projectDir })
).filter(isProjectDirectory) ).filter(isProjectDirectory)
console.log('read_dir_recursive + isProjectDirectory', readProjects)
const projectsWithMetadata = await Promise.all( const projectsWithMetadata = await Promise.all(
readProjects.map(async (p) => ({ readProjects.map(async (p) => ({
@ -73,7 +66,6 @@ export async function getProjectsInDir(projectDir: string) {
...p, ...p,
})) }))
) )
console.log('projectsWithMetadata', projectsWithMetadata)
return projectsWithMetadata return projectsWithMetadata
} }
@ -133,7 +125,6 @@ export async function readProject(projectDir: string) {
const readFiles = await invoke<FileEntry[]>('read_dir_recursive', { const readFiles = await invoke<FileEntry[]>('read_dir_recursive', {
path: projectDir, path: projectDir,
}) })
console.log('read_dir_recursive', readFiles)
return deepFileFilter(readFiles, isRelevantFileOrDir) return deepFileFilter(readFiles, isRelevantFileOrDir)
} }
@ -226,7 +217,7 @@ export async function createNewProject(
}) })
} }
await writeTextFile(path + sep() + PROJECT_ENTRYPOINT, initCode).catch( await writeTextFile(await join(path, PROJECT_ENTRYPOINT), initCode).catch(
(err) => { (err) => {
console.error('Error creating new file:', err) console.error('Error creating new file:', err)
throw err throw err
@ -242,7 +233,7 @@ export async function createNewProject(
children: [ children: [
{ {
name: PROJECT_ENTRYPOINT, name: PROJECT_ENTRYPOINT,
path: path + sep() + PROJECT_ENTRYPOINT, path: await join(path, PROJECT_ENTRYPOINT),
children: [], children: [],
}, },
], ],

View File

@ -1,5 +1,5 @@
import { assign, createMachine } from 'xstate' import { assign, createMachine } from 'xstate'
import { FileEntry, type ProjectWithEntryPointMetadata } from 'lib/types' import type { FileEntry, ProjectWithEntryPointMetadata } from 'lib/types'
export const FILE_PERSIST_KEY = 'Last opened KCL files' export const FILE_PERSIST_KEY = 'Last opened KCL files'
export const DEFAULT_FILE_NAME = 'Untitled' export const DEFAULT_FILE_NAME = 'Untitled'

View File

@ -32,7 +32,7 @@ import useStateMachineCommands from '../hooks/useStateMachineCommands'
import { useGlobalStateContext } from 'hooks/useGlobalStateContext' import { useGlobalStateContext } from 'hooks/useGlobalStateContext'
import { useCommandsContext } from 'hooks/useCommandsContext' import { useCommandsContext } from 'hooks/useCommandsContext'
import { DEFAULT_PROJECT_NAME } from 'machines/settingsMachine' import { DEFAULT_PROJECT_NAME } from 'machines/settingsMachine'
import { sep } from '@tauri-apps/api/path' import { join, sep } from '@tauri-apps/api/path'
import { homeCommandBarConfig } from 'lib/commandBarConfigs/homeCommandConfig' import { homeCommandBarConfig } from 'lib/commandBarConfigs/homeCommandConfig'
import { useHotkeys } from 'react-hotkeys-hook' import { useHotkeys } from 'react-hotkeys-hook'
import { isTauri } from 'lib/isTauri' import { isTauri } from 'lib/isTauri'
@ -120,7 +120,7 @@ const Home = () => {
name = interpolateProjectNameWithIndex(name, nextIndex) name = interpolateProjectNameWithIndex(name, nextIndex)
} }
await createNewProject(context.defaultDirectory + sep() + name) await createNewProject(await join(context.defaultDirectory, name))
if (shouldUpdateDefaultProjectName) { if (shouldUpdateDefaultProjectName) {
sendToSettings({ sendToSettings({
@ -143,8 +143,8 @@ const Home = () => {
} }
await rename( await rename(
context.defaultDirectory + sep() + oldName, await join(context.defaultDirectory, oldName),
context.defaultDirectory + sep() + name, await join(context.defaultDirectory, name),
{} {}
) )
return `Successfully renamed "${oldName}" to "${name}"` return `Successfully renamed "${oldName}" to "${name}"`
@ -153,7 +153,7 @@ const Home = () => {
context: ContextFrom<typeof homeMachine>, context: ContextFrom<typeof homeMachine>,
event: EventFrom<typeof homeMachine, 'Delete project'> event: EventFrom<typeof homeMachine, 'Delete project'>
) => { ) => {
await remove(context.defaultDirectory + sep() + event.data.name, { await remove(await join(context.defaultDirectory, event.data.name), {
recursive: true, recursive: true,
}) })
return `Successfully deleted "${event.data.name}"` return `Successfully deleted "${event.data.name}"`

View File

@ -20,7 +20,7 @@ import { useNavigate } from 'react-router-dom'
import { paths } from 'lib/paths' import { paths } from 'lib/paths'
import { useEffect } from 'react' import { useEffect } from 'react'
import { kclManager } from 'lang/KclSingleton' import { kclManager } from 'lang/KclSingleton'
import { sep } from '@tauri-apps/api/path' import { join, sep } from '@tauri-apps/api/path'
import { APP_NAME } from 'lib/constants' import { APP_NAME } from 'lib/constants'
function OnboardingWithNewFile() { function OnboardingWithNewFile() {
@ -44,12 +44,12 @@ function OnboardingWithNewFile() {
nextIndex nextIndex
) )
const newFile = await createNewProject( const newFile = await createNewProject(
defaultDirectory + sep() + name, await join(defaultDirectory, name),
bracket bracket
) )
navigate( navigate(
`${paths.FILE}/${encodeURIComponent( `${paths.FILE}/${encodeURIComponent(
newFile.path + sep() + PROJECT_ENTRYPOINT await join(newFile.path, PROJECT_ENTRYPOINT)
)}${paths.ONBOARDING.INDEX}` )}${paths.ONBOARDING.INDEX}`
) )
} }

View File

@ -28,7 +28,7 @@ import {
interpolateProjectNameWithIndex, interpolateProjectNameWithIndex,
} from 'lib/tauriFS' } from 'lib/tauriFS'
import { ONBOARDING_PROJECT_NAME } from './Onboarding' import { ONBOARDING_PROJECT_NAME } from './Onboarding'
import { sep } from '@tauri-apps/api/path' import { join, sep } from '@tauri-apps/api/path'
import { bracket } from 'lib/exampleKcl' import { bracket } from 'lib/exampleKcl'
export const Settings = () => { export const Settings = () => {
@ -96,7 +96,7 @@ export const Settings = () => {
nextIndex nextIndex
) )
const newFile = await createNewProject( const newFile = await createNewProject(
defaultDirectory + sep() + name, await join(defaultDirectory, name),
bracket bracket
) )
navigate(`${paths.FILE}/${encodeURIComponent(newFile.path)}`) navigate(`${paths.FILE}/${encodeURIComponent(newFile.path)}`)