Files
modeling-app/src/components/FileMachineProvider.tsx
Pierre Jacquier 544a7565e3 Migrate to tauri v2 (#1400)
* Fix vite build (tauri build still broken)

* Fix yarn builds with a couple of shortcuts

* Fix file creation

* Fix documentDir behavior

* Got stream with default file

* Clean up

* Clean up

* Use 'unstable'; fix devtools callsite

The API changed a bit here, which forces us to use the unstable crate
feature. The call to open devtools is also new; it's now on the
webview not window.

Signed-off-by: Paul R. Tagliamonte <paul@kittycad.io>

* Bring back read_dir_recursive from v1

* Fix dates

* More fixes, incl. conf files

* cargo fmt

* Add Updater plugin

* Fix types

* Fix isTauri detection and updater bootup

* Schemas

* Clean up

* Disable devtools

* Attempt at fixing builds

* WIP Ubuntu dep

* WIP Ubuntu dep

* WIP keys in debug

* Enable updater only on release builds

* Reenable webtools on debug

* No linux bundles

* Typo

* Attemp at fixing --bundles none

* Manual tauri debug build

* Empty commit to trigger the CI

* Fix settings

* Empty commit to trigger the CI

* Merge branch 'main' into pierremtb/issue1349

* Add allow-create perm

* tauri-driver no cap

* Empty commit to trigger the CI

* Clean up

* Clean up

* Migrate to tauri v2
Fixes #1349

* Fix fmt

* Merge branch 'main' into pierremtb/issue1349

* Force BUILD_RELEASE: true

* Bump tauri to new beta

* Merge branch 'main' into pierremtb/issue1349

* Fix linux tests

* Fix types

* Add --verbose to tauri-action

* Move --verbose to front

* Back to tauri-driver@0.1.3 and single \ for win

* Back to latest driver, and windows wip

* Disable release conf temporarily

* Rollback to 2.0.0-beta.2

* Rollback to 2.0.0-beta.1

* Move bundle to root for src-tauri/tauri.release.conf.json

* All packages to latest (add http and shell to package.json)

* Testing latest commit for tauri-action

* Remove tauri action

* Add cat

* WIP

* Update ci.yml

* Disable release conf

* Disable rust cache

* Add tauri-action back for release builds

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* Update .codespellrc

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* Trigger CI

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* Fix type

* Clean up

* More clean up

* Fix path concatenation with join

* Attempt at fixing linux tests

* Config clean up

* Downgrade to tauri-driver@0.1.3

* Looks like tauri v2 is actually doing better with linux package names ah!

* Change Linux apt packages

* Increase wdio connectionRetryTimeout

* Revert connectionRetryTimeout and bump tauri packages

* Back to latest tauri-driver

* Disable linux e2e tests

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* Trigger CI

* Clean up

* Update snapshots

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* Trigger CI

* Remove @sentry/react

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* Rename migrated.json to desktop.json

* A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu)

* Trigger CI

* Change wasm url to http on Windows

---------

Signed-off-by: Paul R. Tagliamonte <paul@kittycad.io>
Co-authored-by: Paul R. Tagliamonte <paul@kittycad.io>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Adam Chalmers <adam.chalmers@zoo.dev>
2024-04-09 08:04:36 -04:00

147 lines
4.3 KiB
TypeScript

import { useMachine } from '@xstate/react'
import { useNavigate, useRouteLoaderData } from 'react-router-dom'
import { type IndexLoaderData } from 'lib/types'
import { paths } from 'lib/paths'
import React, { createContext } from 'react'
import { toast } from 'react-hot-toast'
import {
AnyStateMachine,
ContextFrom,
EventFrom,
InterpreterFrom,
Prop,
StateFrom,
} from 'xstate'
import { useCommandsContext } from 'hooks/useCommandsContext'
import { fileMachine } from 'machines/fileMachine'
import { mkdir, remove, rename, create } from '@tauri-apps/plugin-fs'
import { readProject } from 'lib/tauriFS'
import { isTauri } from 'lib/isTauri'
import { join, sep } from '@tauri-apps/api/path'
import { DEFAULT_FILE_NAME, FILE_EXT } from 'lib/constants'
type MachineContext<T extends AnyStateMachine> = {
state: StateFrom<T>
context: ContextFrom<T>
send: Prop<InterpreterFrom<T>, 'send'>
}
export const FileContext = createContext(
{} as MachineContext<typeof fileMachine>
)
export const FileMachineProvider = ({
children,
}: {
children: React.ReactNode
}) => {
const navigate = useNavigate()
const { commandBarSend } = useCommandsContext()
const { project } = useRouteLoaderData(paths.FILE) as IndexLoaderData
const [state, send] = useMachine(fileMachine, {
context: {
project,
selectedDirectory: project,
},
actions: {
navigateToFile: (context, event) => {
if (event.data && 'name' in event.data) {
commandBarSend({ type: 'Close' })
navigate(
`${paths.FILE}/${encodeURIComponent(
context.selectedDirectory + sep() + event.data.name
)}`
)
}
},
toastSuccess: (_, event) =>
event.data && toast.success((event.data || '') + ''),
toastError: (_, event) => toast.error((event.data || '') + ''),
},
services: {
readFiles: async (context: ContextFrom<typeof fileMachine>) => {
const newFiles = isTauri()
? await readProject(context.project.path)
: []
return {
...context.project,
children: newFiles,
}
},
createFile: async (context, event) => {
let name = event.data.name.trim() || DEFAULT_FILE_NAME
if (event.data.makeDir) {
await mkdir(await join(context.selectedDirectory.path, name))
} else {
await create(
context.selectedDirectory.path +
sep() +
name +
(name.endsWith(FILE_EXT) ? '' : FILE_EXT)
)
}
return `Successfully created "${name}"`
},
renameFile: async (
context: ContextFrom<typeof fileMachine>,
event: EventFrom<typeof fileMachine, 'Rename file'>
) => {
const { oldName, newName, isDir } = event.data
let name = newName ? newName : DEFAULT_FILE_NAME
await rename(
await join(context.selectedDirectory.path, oldName),
(await join(context.selectedDirectory.path, name)) +
(name.endsWith(FILE_EXT) || isDir ? '' : FILE_EXT),
{}
)
return (
oldName !== name && `Successfully renamed "${oldName}" to "${name}"`
)
},
deleteFile: async (
context: ContextFrom<typeof fileMachine>,
event: EventFrom<typeof fileMachine, 'Delete file'>
) => {
const isDir = !!event.data.children
if (isDir) {
await remove(event.data.path, {
recursive: true,
}).catch((e) => console.error('Error deleting directory', e))
} else {
await remove(event.data.path).catch((e) =>
console.error('Error deleting file', e)
)
}
return `Successfully deleted ${isDir ? 'folder' : 'file'} "${
event.data.name
}"`
},
},
guards: {
'Has at least 1 file': (_, event: EventFrom<typeof fileMachine>) => {
if (event.type !== 'done.invoke.read-files') return false
return !!event?.data?.children && event.data.children.length > 0
},
},
})
return (
<FileContext.Provider
value={{
send,
state,
context: state.context, // just a convenience, can remove if we need to save on memory
}}
>
{children}
</FileContext.Provider>
)
}
export default FileMachineProvider