In the middle of replacing fs and project functions
This commit is contained in:
@ -16,7 +16,7 @@ import { useEngineConnectionSubscriptions } from 'hooks/useEngineConnectionSubsc
|
|||||||
import { engineCommandManager } from 'lib/singletons'
|
import { engineCommandManager } from 'lib/singletons'
|
||||||
import { useModelingContext } from 'hooks/useModelingContext'
|
import { useModelingContext } from 'hooks/useModelingContext'
|
||||||
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
|
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { useLspContext } from 'components/LspProvider'
|
import { useLspContext } from 'components/LspProvider'
|
||||||
import { useRefreshSettings } from 'hooks/useRefreshSettings'
|
import { useRefreshSettings } from 'hooks/useRefreshSettings'
|
||||||
import { ModelingSidebar } from 'components/ModelingSidebar/ModelingSidebar'
|
import { ModelingSidebar } from 'components/ModelingSidebar/ModelingSidebar'
|
||||||
@ -62,7 +62,7 @@ export function App() {
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
})
|
})
|
||||||
useHotkeyWrapper(
|
useHotkeyWrapper(
|
||||||
[isTauri() ? 'mod + ,' : 'shift + mod + ,'],
|
[isDesktop() ? 'mod + ,' : 'shift + mod + ,'],
|
||||||
() => navigate(filePath + paths.SETTINGS),
|
() => navigate(filePath + paths.SETTINGS),
|
||||||
{
|
{
|
||||||
splitKey: '|',
|
splitKey: '|',
|
||||||
|
@ -10,7 +10,7 @@ import { Settings } from './routes/Settings'
|
|||||||
import Onboarding, { onboardingRoutes } from './routes/Onboarding'
|
import Onboarding, { onboardingRoutes } from './routes/Onboarding'
|
||||||
import SignIn from './routes/SignIn'
|
import SignIn from './routes/SignIn'
|
||||||
import { Auth } from './Auth'
|
import { Auth } from './Auth'
|
||||||
import { isTauri } from './lib/isTauri'
|
import { isDesktop } from './lib/isDesktop'
|
||||||
import Home from './routes/Home'
|
import Home from './routes/Home'
|
||||||
import { NetworkContext } from './hooks/useNetworkContext'
|
import { NetworkContext } from './hooks/useNetworkContext'
|
||||||
import { useNetworkStatus } from './hooks/useNetworkStatus'
|
import { useNetworkStatus } from './hooks/useNetworkStatus'
|
||||||
@ -32,7 +32,7 @@ import SettingsAuthProvider from 'components/SettingsAuthProvider'
|
|||||||
import LspProvider from 'components/LspProvider'
|
import LspProvider from 'components/LspProvider'
|
||||||
import { KclContextProvider } from 'lang/KclProvider'
|
import { KclContextProvider } from 'lang/KclProvider'
|
||||||
import { BROWSER_PROJECT_NAME } from 'lib/constants'
|
import { BROWSER_PROJECT_NAME } from 'lib/constants'
|
||||||
import { getState, setState } from 'lib/tauri'
|
import { getState, setState } from 'lib/desktop'
|
||||||
import { CoreDumpManager } from 'lib/coredump'
|
import { CoreDumpManager } from 'lib/coredump'
|
||||||
import { engineCommandManager } from 'lib/singletons'
|
import { engineCommandManager } from 'lib/singletons'
|
||||||
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
||||||
@ -66,8 +66,8 @@ const router = createBrowserRouter([
|
|||||||
{
|
{
|
||||||
path: paths.INDEX,
|
path: paths.INDEX,
|
||||||
loader: async () => {
|
loader: async () => {
|
||||||
const inTauri = isTauri()
|
const onDesktop = isDesktop()
|
||||||
if (inTauri) {
|
if (onDesktop) {
|
||||||
const appState = await getState()
|
const appState = await getState()
|
||||||
|
|
||||||
if (appState) {
|
if (appState) {
|
||||||
@ -84,7 +84,7 @@ const router = createBrowserRouter([
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return inTauri
|
return onDesktop
|
||||||
? redirect(paths.HOME)
|
? redirect(paths.HOME)
|
||||||
: redirect(paths.FILE + '/%2F' + BROWSER_PROJECT_NAME)
|
: redirect(paths.FILE + '/%2F' + BROWSER_PROJECT_NAME)
|
||||||
},
|
},
|
||||||
@ -101,7 +101,7 @@ const router = createBrowserRouter([
|
|||||||
<Outlet />
|
<Outlet />
|
||||||
<App />
|
<App />
|
||||||
<CommandBar />
|
<CommandBar />
|
||||||
{!isTauri() && import.meta.env.PROD && <DownloadAppBanner />}
|
{!isDesktop() && import.meta.env.PROD && <DownloadAppBanner />}
|
||||||
</ModelingMachineProvider>
|
</ModelingMachineProvider>
|
||||||
<WasmErrBanner />
|
<WasmErrBanner />
|
||||||
</FileMachineProvider>
|
</FileMachineProvider>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { useRouteError, isRouteErrorResponse } from 'react-router-dom'
|
import { useRouteError, isRouteErrorResponse } from 'react-router-dom'
|
||||||
import { ActionButton } from './ActionButton'
|
import { ActionButton } from './ActionButton'
|
||||||
import {
|
import {
|
||||||
@ -25,7 +25,7 @@ export const ErrorPage = () => {
|
|||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
<div className="flex justify-between gap-2 mt-6">
|
<div className="flex justify-between gap-2 mt-6">
|
||||||
{isTauri() && (
|
{isDesktop() && (
|
||||||
<ActionButton
|
<ActionButton
|
||||||
Element="link"
|
Element="link"
|
||||||
to={'/'}
|
to={'/'}
|
||||||
|
@ -16,7 +16,7 @@ import {
|
|||||||
import { useCommandsContext } from 'hooks/useCommandsContext'
|
import { useCommandsContext } from 'hooks/useCommandsContext'
|
||||||
import { fileMachine } from 'machines/fileMachine'
|
import { 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 { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { join, sep } from '@tauri-apps/api/path'
|
import { join, sep } from '@tauri-apps/api/path'
|
||||||
import { DEFAULT_FILE_NAME, FILE_EXT } from 'lib/constants'
|
import { DEFAULT_FILE_NAME, FILE_EXT } from 'lib/constants'
|
||||||
import { getProjectInfo } from 'lib/tauri'
|
import { getProjectInfo } from 'lib/tauri'
|
||||||
@ -86,7 +86,7 @@ export const FileMachineProvider = ({
|
|||||||
},
|
},
|
||||||
services: {
|
services: {
|
||||||
readFiles: async (context: ContextFrom<typeof fileMachine>) => {
|
readFiles: async (context: ContextFrom<typeof fileMachine>) => {
|
||||||
const newFiles = isTauri()
|
const newFiles = isDesktop()
|
||||||
? (await getProjectInfo(context.project.path)).children
|
? (await getProjectInfo(context.project.path)).children
|
||||||
: []
|
: []
|
||||||
return {
|
return {
|
||||||
|
@ -25,7 +25,7 @@ import {
|
|||||||
import { wasmUrl } from 'lang/wasm'
|
import { wasmUrl } from 'lang/wasm'
|
||||||
import { PROJECT_ENTRYPOINT } from 'lib/constants'
|
import { PROJECT_ENTRYPOINT } from 'lib/constants'
|
||||||
import { err } from 'lib/trap'
|
import { err } from 'lib/trap'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { codeManager } from 'lib/singletons'
|
import { codeManager } from 'lib/singletons'
|
||||||
|
|
||||||
function getWorkspaceFolders(): LSP.WorkspaceFolder[] {
|
function getWorkspaceFolders(): LSP.WorkspaceFolder[] {
|
||||||
@ -125,7 +125,7 @@ export const LspProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
])
|
])
|
||||||
|
|
||||||
useMemo(() => {
|
useMemo(() => {
|
||||||
if (!isTauri() && isKclLspReady && kclLspClient && codeManager.code) {
|
if (!isDesktop() && isKclLspReady && kclLspClient && codeManager.code) {
|
||||||
kclLspClient.textDocumentDidOpen({
|
kclLspClient.textDocumentDidOpen({
|
||||||
textDocument: {
|
textDocument: {
|
||||||
uri: `file:///${PROJECT_ENTRYPOINT}`,
|
uri: `file:///${PROJECT_ENTRYPOINT}`,
|
||||||
|
@ -7,7 +7,7 @@ import Tooltip from 'components/Tooltip'
|
|||||||
import { ActionIcon } from 'components/ActionIcon'
|
import { ActionIcon } from 'components/ActionIcon'
|
||||||
import styles from './ModelingSidebar.module.css'
|
import styles from './ModelingSidebar.module.css'
|
||||||
import { ModelingPane } from './ModelingPane'
|
import { ModelingPane } from './ModelingPane'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { useModelingContext } from 'hooks/useModelingContext'
|
import { useModelingContext } from 'hooks/useModelingContext'
|
||||||
import { CustomIconName } from 'components/CustomIcon'
|
import { CustomIconName } from 'components/CustomIcon'
|
||||||
import { useCommandsContext } from 'hooks/useCommandsContext'
|
import { useCommandsContext } from 'hooks/useCommandsContext'
|
||||||
@ -142,7 +142,110 @@ export function ModelingSidebar({ paneOpacity }: ModelingSidebarProps) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div id="app-sidebar" className={styles.grid + ' flex-1'}>
|
<div id="app-sidebar" className={styles.grid + ' flex-1'}>
|
||||||
<ul
|
<ModelingSidebarSection id="sidebar-top" panes={topPanes} />
|
||||||
|
<ModelingSidebarSection
|
||||||
|
id="sidebar-bottom"
|
||||||
|
panes={bottomPanes}
|
||||||
|
alignButtons="end"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Resizable>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ModelingSidebarSectionProps extends HTMLAttributes<HTMLDivElement> {
|
||||||
|
panes: SidebarPane[]
|
||||||
|
alignButtons?: 'start' | 'end'
|
||||||
|
}
|
||||||
|
|
||||||
|
function ModelingSidebarSection({
|
||||||
|
panes,
|
||||||
|
alignButtons = 'start',
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: ModelingSidebarSectionProps) {
|
||||||
|
const { settings } = useSettingsAuthContext()
|
||||||
|
const showDebugPanel = settings.context.modeling.showDebugPanel
|
||||||
|
const paneIds = panes.map((pane) => pane.id)
|
||||||
|
const { send, context } = useModelingContext()
|
||||||
|
const foundOpenPane = context.store?.openPanes.find((pane) =>
|
||||||
|
paneIds.includes(pane)
|
||||||
|
)
|
||||||
|
const [currentPane, setCurrentPane] = useState(
|
||||||
|
foundOpenPane || ('none' as SidebarType | 'none')
|
||||||
|
)
|
||||||
|
|
||||||
|
const togglePane = useCallback(
|
||||||
|
(newPane: SidebarType | 'none') => {
|
||||||
|
if (newPane === 'none') {
|
||||||
|
send({
|
||||||
|
type: 'Set context',
|
||||||
|
data: {
|
||||||
|
openPanes: context.store?.openPanes.filter(
|
||||||
|
(p) => p !== currentPane
|
||||||
|
),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
setCurrentPane('none')
|
||||||
|
} else if (newPane === currentPane) {
|
||||||
|
setCurrentPane('none')
|
||||||
|
send({
|
||||||
|
type: 'Set context',
|
||||||
|
data: {
|
||||||
|
openPanes: context.store?.openPanes.filter((p) => p !== newPane),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
send({
|
||||||
|
type: 'Set context',
|
||||||
|
data: {
|
||||||
|
openPanes: [
|
||||||
|
...context.store?.openPanes.filter((p) => p !== currentPane),
|
||||||
|
newPane,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
setCurrentPane(newPane)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[context.store?.openPanes, send, currentPane, setCurrentPane]
|
||||||
|
)
|
||||||
|
|
||||||
|
// Filter out the debug panel if it's not supposed to be shown
|
||||||
|
// TODO: abstract out for allowing user to configure which panes to show
|
||||||
|
const filteredPanes = (
|
||||||
|
showDebugPanel.current ? panes : panes.filter((pane) => pane.id !== 'debug')
|
||||||
|
).filter(
|
||||||
|
(pane) =>
|
||||||
|
!pane.hideOnPlatform ||
|
||||||
|
(isDesktop()
|
||||||
|
? pane.hideOnPlatform === 'web'
|
||||||
|
: pane.hideOnPlatform === 'desktop')
|
||||||
|
)
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
!showDebugPanel.current &&
|
||||||
|
currentPane === 'debug' &&
|
||||||
|
context.store?.openPanes.includes('debug')
|
||||||
|
) {
|
||||||
|
togglePane('debug')
|
||||||
|
}
|
||||||
|
}, [showDebugPanel.current, togglePane, context.store?.openPanes])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={'group contents ' + className} {...props}>
|
||||||
|
<Tab.Group
|
||||||
|
vertical
|
||||||
|
selectedIndex={
|
||||||
|
currentPane === 'none' ? 0 : paneIds.indexOf(currentPane) + 1
|
||||||
|
}
|
||||||
|
onChange={(index) => {
|
||||||
|
const newPane = index === 0 ? 'none' : paneIds[index - 1]
|
||||||
|
togglePane(newPane)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Tab.List
|
||||||
|
id={`${props.id}-ribbon`}
|
||||||
className={
|
className={
|
||||||
(context.store?.openPanes.length === 0 ? 'rounded-r ' : '') +
|
(context.store?.openPanes.length === 0 ? 'rounded-r ' : '') +
|
||||||
'relative z-[2] pointer-events-auto p-0 col-start-1 col-span-1 h-fit w-fit flex flex-col ' +
|
'relative z-[2] pointer-events-auto p-0 col-start-1 col-span-1 h-fit w-fit flex flex-col ' +
|
||||||
|
@ -2,7 +2,7 @@ import { Popover, Transition } from '@headlessui/react'
|
|||||||
import { ActionButton, ActionButtonProps } from './ActionButton'
|
import { ActionButton, ActionButtonProps } from './ActionButton'
|
||||||
import { type IndexLoaderData } from 'lib/types'
|
import { type IndexLoaderData } from 'lib/types'
|
||||||
import { paths } from 'lib/paths'
|
import { paths } from 'lib/paths'
|
||||||
import { isTauri } from '../lib/isTauri'
|
import { isDesktop } from '../lib/isDesktop'
|
||||||
import { Link, useLocation, useNavigate } from 'react-router-dom'
|
import { Link, useLocation, useNavigate } from 'react-router-dom'
|
||||||
import { Fragment, useMemo } from 'react'
|
import { Fragment, useMemo } from 'react'
|
||||||
import { sep } from '@tauri-apps/api/path'
|
import { sep } from '@tauri-apps/api/path'
|
||||||
@ -55,7 +55,7 @@ function AppLogoLink({
|
|||||||
"relative h-full grid place-content-center group p-1.5 before:block before:content-[''] before:absolute before:inset-0 before:bottom-2.5 before:z-[-1] before:bg-primary before:rounded-b-sm"
|
"relative h-full grid place-content-center group p-1.5 before:block before:content-[''] before:absolute before:inset-0 before:bottom-2.5 before:z-[-1] before:bg-primary before:rounded-b-sm"
|
||||||
const logoClassName = 'w-auto h-4 text-chalkboard-10'
|
const logoClassName = 'w-auto h-4 text-chalkboard-10'
|
||||||
|
|
||||||
return isTauri() ? (
|
return isDesktop() ? (
|
||||||
<Link
|
<Link
|
||||||
data-testid="app-logo"
|
data-testid="app-logo"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@ -111,7 +111,7 @@ function ProjectMenuPopover({
|
|||||||
<>
|
<>
|
||||||
<span className="flex-1">Project settings</span>
|
<span className="flex-1">Project settings</span>
|
||||||
<kbd className="hotkey">{`${platform === 'macos' ? '⌘' : 'Ctrl'}${
|
<kbd className="hotkey">{`${platform === 'macos' ? '⌘' : 'Ctrl'}${
|
||||||
isTauri() ? '' : '⬆'
|
isDesktop() ? '' : '⬆'
|
||||||
},`}</kbd>
|
},`}</kbd>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
@ -177,7 +177,7 @@ function ProjectMenuPopover({
|
|||||||
id: 'go-home',
|
id: 'go-home',
|
||||||
Element: 'button',
|
Element: 'button',
|
||||||
children: 'Go to Home',
|
children: 'Go to Home',
|
||||||
className: !isTauri() ? 'hidden' : '',
|
className: !isDesktop() ? 'hidden' : '',
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
onProjectClose(file || null, project?.path || null, true)
|
onProjectClose(file || null, project?.path || null, true)
|
||||||
// Clear the scene and end the session.
|
// Clear the scene and end the session.
|
||||||
@ -195,7 +195,7 @@ function ProjectMenuPopover({
|
|||||||
commandBarSend,
|
commandBarSend,
|
||||||
engineCommandManager,
|
engineCommandManager,
|
||||||
onProjectClose,
|
onProjectClose,
|
||||||
isTauri,
|
isDesktop,
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -207,11 +207,11 @@ function ProjectMenuPopover({
|
|||||||
>
|
>
|
||||||
<div className="flex flex-col items-start py-0.5">
|
<div className="flex flex-col items-start py-0.5">
|
||||||
<span className="hidden text-sm text-chalkboard-110 dark:text-chalkboard-20 whitespace-nowrap lg:block">
|
<span className="hidden text-sm text-chalkboard-110 dark:text-chalkboard-20 whitespace-nowrap lg:block">
|
||||||
{isTauri() && file?.name
|
{isDesktop() && file?.name
|
||||||
? file.name.slice(file.name.lastIndexOf(sep()) + 1)
|
? file.name.slice(file.name.lastIndexOf(sep()) + 1)
|
||||||
: APP_NAME}
|
: APP_NAME}
|
||||||
</span>
|
</span>
|
||||||
{isTauri() && project?.name && (
|
{isDesktop() && project?.name && (
|
||||||
<span className="hidden text-xs text-chalkboard-70 dark:text-chalkboard-40 whitespace-nowrap lg:block">
|
<span className="hidden text-xs text-chalkboard-70 dark:text-chalkboard-40 whitespace-nowrap lg:block">
|
||||||
{project.name}
|
{project.name}
|
||||||
</span>
|
</span>
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
import { Fragment } from 'react/jsx-runtime'
|
import { Fragment } from 'react/jsx-runtime'
|
||||||
import { SettingsSection } from './SettingsSection'
|
import { SettingsSection } from './SettingsSection'
|
||||||
import { useLocation, useNavigate } from 'react-router-dom'
|
import { useLocation, useNavigate } from 'react-router-dom'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { ActionButton } from 'components/ActionButton'
|
import { ActionButton } from 'components/ActionButton'
|
||||||
import { SettingsFieldInput } from './SettingsFieldInput'
|
import { SettingsFieldInput } from './SettingsFieldInput'
|
||||||
import { getInitialDefaultDir, showInFolder } from 'lib/tauri'
|
import { getInitialDefaultDir, showInFolder } from 'lib/tauri'
|
||||||
@ -41,7 +41,7 @@ export const AllSettingsFields = forwardRef(
|
|||||||
} = useSettingsAuthContext()
|
} = useSettingsAuthContext()
|
||||||
|
|
||||||
const projectPath =
|
const projectPath =
|
||||||
isFileSettings && isTauri()
|
isFileSettings && isDesktop()
|
||||||
? decodeURI(
|
? decodeURI(
|
||||||
location.pathname
|
location.pathname
|
||||||
.replace(paths.FILE + '/', '')
|
.replace(paths.FILE + '/', '')
|
||||||
@ -176,14 +176,14 @@ export const AllSettingsFields = forwardRef(
|
|||||||
title="Reset settings"
|
title="Reset settings"
|
||||||
description={`Restore settings to their default values. Your settings are saved in
|
description={`Restore settings to their default values. Your settings are saved in
|
||||||
${
|
${
|
||||||
isTauri()
|
isDesktop()
|
||||||
? ' a file in the app data folder for your OS.'
|
? ' a file in the app data folder for your OS.'
|
||||||
: " your browser's local storage."
|
: " your browser's local storage."
|
||||||
}
|
}
|
||||||
`}
|
`}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col items-start gap-4">
|
<div className="flex flex-col items-start gap-4">
|
||||||
{isTauri() && (
|
{isDesktop() && (
|
||||||
<ActionButton
|
<ActionButton
|
||||||
Element="button"
|
Element="button"
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
|
@ -21,7 +21,7 @@ import {
|
|||||||
Prop,
|
Prop,
|
||||||
StateFrom,
|
StateFrom,
|
||||||
} from 'xstate'
|
} from 'xstate'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { authCommandBarConfig } from 'lib/commandBarConfigs/authCommandConfig'
|
import { authCommandBarConfig } from 'lib/commandBarConfigs/authCommandConfig'
|
||||||
import { kclManager, sceneInfra, engineCommandManager } from 'lib/singletons'
|
import { kclManager, sceneInfra, engineCommandManager } from 'lib/singletons'
|
||||||
import { uuidv4 } from 'lib/utils'
|
import { uuidv4 } from 'lib/utils'
|
||||||
@ -341,7 +341,7 @@ export default SettingsAuthProvider
|
|||||||
export function logout() {
|
export function logout() {
|
||||||
localStorage.removeItem(TOKEN_PERSIST_KEY)
|
localStorage.removeItem(TOKEN_PERSIST_KEY)
|
||||||
return (
|
return (
|
||||||
!isTauri() &&
|
!isDesktop() &&
|
||||||
fetch(withBaseUrl('/logout'), {
|
fetch(withBaseUrl('/logout'), {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
|
@ -8,7 +8,7 @@ import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
|||||||
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
|
import { useAbsoluteFilePath } from 'hooks/useAbsoluteFilePath'
|
||||||
import Tooltip from './Tooltip'
|
import Tooltip from './Tooltip'
|
||||||
import usePlatform from 'hooks/usePlatform'
|
import usePlatform from 'hooks/usePlatform'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { CustomIcon } from './CustomIcon'
|
import { CustomIcon } from './CustomIcon'
|
||||||
|
|
||||||
type User = Models['User_type']
|
type User = Models['User_type']
|
||||||
@ -33,7 +33,7 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
|
|||||||
<>
|
<>
|
||||||
<span className="flex-1">User settings</span>
|
<span className="flex-1">User settings</span>
|
||||||
<kbd className="hotkey">{`${platform === 'macos' ? '⌘' : 'Ctrl'}${
|
<kbd className="hotkey">{`${platform === 'macos' ? '⌘' : 'Ctrl'}${
|
||||||
isTauri() ? '' : '⬆'
|
isDesktop() ? '' : '⬆'
|
||||||
},`}</kbd>
|
},`}</kbd>
|
||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Platform, platform } from '@tauri-apps/plugin-os'
|
import { Platform, platform } from '@tauri-apps/plugin-os'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
export default function usePlatform() {
|
export default function usePlatform() {
|
||||||
@ -10,7 +10,7 @@ export default function usePlatform() {
|
|||||||
setPlatformName(await platform())
|
setPlatformName(await platform())
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTauri()) {
|
if (isDesktop()) {
|
||||||
void getPlatform()
|
void getPlatform()
|
||||||
} else {
|
} else {
|
||||||
if (navigator.userAgent.indexOf('Mac') !== -1) {
|
if (navigator.userAgent.indexOf('Mac') !== -1) {
|
||||||
|
@ -6,7 +6,7 @@ import { Router } from './Router'
|
|||||||
import { HotkeysProvider } from 'react-hotkeys-hook'
|
import { HotkeysProvider } from 'react-hotkeys-hook'
|
||||||
import ModalContainer from 'react-modal-promise'
|
import ModalContainer from 'react-modal-promise'
|
||||||
import { UpdaterModal, createUpdaterModal } from 'components/UpdaterModal'
|
import { UpdaterModal, createUpdaterModal } from 'components/UpdaterModal'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { relaunch } from '@tauri-apps/plugin-process'
|
import { relaunch } from '@tauri-apps/plugin-process'
|
||||||
import { check } from '@tauri-apps/plugin-updater'
|
import { check } from '@tauri-apps/plugin-updater'
|
||||||
import {
|
import {
|
||||||
@ -84,4 +84,4 @@ const runTauriUpdater = async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isTauri() && runTauriUpdater()
|
isDesktop() && runTauriUpdater()
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
// NOT updating the code state when we don't need to.
|
// NOT updating the code state when we don't need to.
|
||||||
// This prevents re-renders of the codemirror editor, when typing.
|
// This prevents re-renders of the codemirror editor, when typing.
|
||||||
import { bracket } from 'lib/exampleKcl'
|
import { bracket } from 'lib/exampleKcl'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { writeTextFile } from '@tauri-apps/plugin-fs'
|
import { writeTextFile } from '@tauri-apps/plugin-fs'
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import { editorManager } from 'lib/singletons'
|
import { editorManager } from 'lib/singletons'
|
||||||
@ -21,7 +21,7 @@ export default class CodeManager {
|
|||||||
private _hotkeys: { [key: string]: () => void } = {}
|
private _hotkeys: { [key: string]: () => void } = {}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
if (isTauri()) {
|
if (isDesktop()) {
|
||||||
this.code = ''
|
this.code = ''
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -115,7 +115,7 @@ export default class CodeManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async writeToFile() {
|
async writeToFile() {
|
||||||
if (isTauri()) {
|
if (isDesktop()) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// Wait one event loop to give a chance for params to be set
|
// Wait one event loop to give a chance for params to be set
|
||||||
// Save the file to disk
|
// Save the file to disk
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
import { readFile, exists as tauriExists } from '@tauri-apps/plugin-fs'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { isTauri } from 'lib/isTauri'
|
|
||||||
import { join } from '@tauri-apps/api/path'
|
|
||||||
import { readDirRecursive } from 'lib/tauri'
|
|
||||||
|
|
||||||
/// FileSystemManager is a class that provides a way to read files from the local file system.
|
/// FileSystemManager is a class that provides a way to read files from the local file system.
|
||||||
/// It assumes that you are in a project since it is solely used by the std lib
|
/// It assumes that you are in a project since it is solely used by the std lib
|
||||||
@ -17,54 +14,58 @@ class FileSystemManager {
|
|||||||
this._dir = dir
|
this._dir = dir
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async join(dir: string, path: string): Promise<string> {
|
||||||
|
return window.electron.ipcRenderer.invoke('join', [dir, path]);
|
||||||
|
}
|
||||||
|
|
||||||
async readFile(path: string): Promise<Uint8Array | void> {
|
async readFile(path: string): Promise<Uint8Array | void> {
|
||||||
// Using local file system only works from Tauri.
|
// Using local file system only works from desktop.
|
||||||
if (!isTauri()) {
|
if (!isDesktop()) {
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
new Error('This function can only be called from a Tauri application')
|
new Error('This function can only be called from the desktop application')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return join(this.dir, path)
|
return this.join(this.dir, path)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
return Promise.reject(new Error(`Error reading file: ${error}`))
|
return Promise.reject(new Error(`Error reading file: ${error}`))
|
||||||
})
|
})
|
||||||
.then((file) => {
|
.then((file) => {
|
||||||
return readFile(file)
|
return window.electron.ipcRenderer.invoke('readFile', [filepath])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async exists(path: string): Promise<boolean | void> {
|
async exists(path: string): Promise<boolean | void> {
|
||||||
// Using local file system only works from Tauri.
|
// Using local file system only works from desktop.
|
||||||
if (!isTauri()) {
|
if (!isDesktop()) {
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
new Error('This function can only be called from a Tauri application')
|
new Error('This function can only be called from the desktop application')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return join(this.dir, path)
|
return this.join(this.dir, path)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
return Promise.reject(new Error(`Error checking file exists: ${error}`))
|
return Promise.reject(new Error(`Error checking file exists: ${error}`))
|
||||||
})
|
})
|
||||||
.then((file) => {
|
.then((file) => {
|
||||||
return tauriExists(file)
|
return window.electron.ipcRenderer.invoke('exists', [file])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllFiles(path: string): Promise<string[] | void> {
|
async getAllFiles(path: string): Promise<string[] | void> {
|
||||||
// Using local file system only works from Tauri.
|
// Using local file system only works from desktop.
|
||||||
if (!isTauri()) {
|
if (!isDesktop()) {
|
||||||
return Promise.reject(
|
return Promise.reject(
|
||||||
new Error('This function can only be called from a Tauri application')
|
new Error('This function can only be called from the desktop application')
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return join(this.dir, path)
|
return this.join(this.dir, path)
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
return Promise.reject(new Error(`Error joining dir: ${error}`))
|
return Promise.reject(new Error(`Error joining dir: ${error}`))
|
||||||
})
|
})
|
||||||
.then((p) => {
|
.then((filepath) => {
|
||||||
readDirRecursive(p)
|
return window.electron.ipcRenderer.invoke('readdir', [filepath])
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
return Promise.reject(new Error(`Error reading dir: ${error}`))
|
return Promise.reject(new Error(`Error reading dir: ${error}`))
|
||||||
})
|
})
|
||||||
|
@ -14,7 +14,7 @@ import { AnyStateMachine, ContextFrom, InterpreterFrom } from 'xstate'
|
|||||||
import { getPropertyByPath } from 'lib/objectPropertyByPath'
|
import { getPropertyByPath } from 'lib/objectPropertyByPath'
|
||||||
import { buildCommandArgument } from 'lib/createMachineCommand'
|
import { buildCommandArgument } from 'lib/createMachineCommand'
|
||||||
import decamelize from 'decamelize'
|
import decamelize from 'decamelize'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { Setting } from 'lib/settings/initialSettings'
|
import { Setting } from 'lib/settings/initialSettings'
|
||||||
|
|
||||||
// An array of the paths to all of the settings that have commandConfigs
|
// An array of the paths to all of the settings that have commandConfigs
|
||||||
@ -78,7 +78,7 @@ export function createSettingsCommand({
|
|||||||
settingConfig?.hideOnLevel === 'user' && !isProjectAvailable
|
settingConfig?.hideOnLevel === 'user' && !isProjectAvailable
|
||||||
const shouldHideOnThisPlatform =
|
const shouldHideOnThisPlatform =
|
||||||
settingConfig.hideOnPlatform &&
|
settingConfig.hideOnPlatform &&
|
||||||
(isTauri()
|
(isDesktop()
|
||||||
? settingConfig.hideOnPlatform === 'desktop'
|
? settingConfig.hideOnPlatform === 'desktop'
|
||||||
: settingConfig.hideOnPlatform === 'web')
|
: settingConfig.hideOnPlatform === 'web')
|
||||||
if (
|
if (
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { CommandLog, EngineCommandManager } from 'lang/std/engineConnection'
|
import { CommandLog, EngineCommandManager } from 'lang/std/engineConnection'
|
||||||
import { WebrtcStats } from 'wasm-lib/kcl/bindings/WebrtcStats'
|
import { WebrtcStats } from 'wasm-lib/kcl/bindings/WebrtcStats'
|
||||||
import { OsInfo } from 'wasm-lib/kcl/bindings/OsInfo'
|
import { OsInfo } from 'wasm-lib/kcl/bindings/OsInfo'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import {
|
import {
|
||||||
platform as tauriPlatform,
|
platform as tauriPlatform,
|
||||||
arch as tauriArch,
|
arch as tauriArch,
|
||||||
@ -68,7 +68,7 @@ export class CoreDumpManager {
|
|||||||
|
|
||||||
// Get the os information.
|
// Get the os information.
|
||||||
getOsInfo(): Promise<string> {
|
getOsInfo(): Promise<string> {
|
||||||
if (this.isTauri()) {
|
if (this.isDesktop()) {
|
||||||
const osinfo: OsInfo = {
|
const osinfo: OsInfo = {
|
||||||
platform: tauriPlatform(),
|
platform: tauriPlatform(),
|
||||||
arch: tauriArch(),
|
arch: tauriArch(),
|
||||||
@ -101,8 +101,8 @@ export class CoreDumpManager {
|
|||||||
return new Promise((resolve) => resolve(JSON.stringify(osinfo)))
|
return new Promise((resolve) => resolve(JSON.stringify(osinfo)))
|
||||||
}
|
}
|
||||||
|
|
||||||
isTauri(): boolean {
|
isDesktop(): boolean {
|
||||||
return isTauri()
|
return isDesktop()
|
||||||
}
|
}
|
||||||
|
|
||||||
getWebrtcStats(): Promise<string> {
|
getWebrtcStats(): Promise<string> {
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
InterpreterFrom,
|
InterpreterFrom,
|
||||||
StateFrom,
|
StateFrom,
|
||||||
} from 'xstate'
|
} from 'xstate'
|
||||||
import { isTauri } from './isTauri'
|
import { isDesktop } from './isDesktop'
|
||||||
import {
|
import {
|
||||||
Command,
|
Command,
|
||||||
CommandArgument,
|
CommandArgument,
|
||||||
@ -76,8 +76,8 @@ export function createMachineCommand<
|
|||||||
if ('hide' in commandConfig) {
|
if ('hide' in commandConfig) {
|
||||||
const { hide } = commandConfig
|
const { hide } = commandConfig
|
||||||
if (hide === 'both') return null
|
if (hide === 'both') return null
|
||||||
else if (hide === 'desktop' && isTauri()) return null
|
else if (hide === 'desktop' && isDesktop()) return null
|
||||||
else if (hide === 'web' && !isTauri()) return null
|
else if (hide === 'web' && !isDesktop()) return null
|
||||||
}
|
}
|
||||||
|
|
||||||
const icon = ('icon' in commandConfig && commandConfig.icon) || undefined
|
const icon = ('icon' in commandConfig && commandConfig.icon) || undefined
|
||||||
|
@ -1,30 +1,31 @@
|
|||||||
// This file contains wrappers around the tauri commands we define in rust code.
|
|
||||||
|
|
||||||
import { Models } from '@kittycad/lib/dist/types/src'
|
import { Models } from '@kittycad/lib/dist/types/src'
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
|
||||||
import { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
|
import { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
|
||||||
import { ProjectConfiguration } from 'wasm-lib/kcl/bindings/ProjectConfiguration'
|
import { ProjectConfiguration } from 'wasm-lib/kcl/bindings/ProjectConfiguration'
|
||||||
import { Project } from 'wasm-lib/kcl/bindings/Project'
|
import { Project } from 'wasm-lib/kcl/bindings/Project'
|
||||||
import { FileEntry } from 'wasm-lib/kcl/bindings/FileEntry'
|
import { FileEntry } from 'wasm-lib/kcl/bindings/FileEntry'
|
||||||
import { ProjectState } from 'wasm-lib/kcl/bindings/ProjectState'
|
import { ProjectState } from 'wasm-lib/kcl/bindings/ProjectState'
|
||||||
import { ProjectRoute } from 'wasm-lib/kcl/bindings/ProjectRoute'
|
import { ProjectRoute } from 'wasm-lib/kcl/bindings/ProjectRoute'
|
||||||
import { isTauri } from './isTauri'
|
|
||||||
import { components } from './machine-api'
|
import { components } from './machine-api'
|
||||||
|
import { isDesktop } from './isDesktop'
|
||||||
|
|
||||||
// Get the app state from tauri.
|
// All these functions call into lib/electron since many require filesystem
|
||||||
|
// access, and the second half is the original tauri code also stored app
|
||||||
|
// state on the "desktop" side.
|
||||||
|
|
||||||
|
// Get the app state from desktop.
|
||||||
export async function getState(): Promise<ProjectState | undefined> {
|
export async function getState(): Promise<ProjectState | undefined> {
|
||||||
if (!isTauri()) {
|
if (!isDesktop()) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
return await invoke<ProjectState | undefined>('get_state')
|
return await window.electron.ipcRenderer.invoke('get_state')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the app state in tauri.
|
// Set the app state in desktop.
|
||||||
export async function setState(state: ProjectState | undefined): Promise<void> {
|
export async function setState(state: ProjectState | undefined): Promise<void> {
|
||||||
if (!isTauri()) {
|
if (!isDesktop()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return await invoke('set_state', { state })
|
return window.electron.ipcRenderer.invoke('set_state', { state })
|
||||||
}
|
}
|
||||||
|
|
||||||
// List machines on the local network.
|
// List machines on the local network.
|
||||||
@ -49,30 +50,30 @@ export async function renameProjectDirectory(
|
|||||||
|
|
||||||
// Get the initial default dir for holding all projects.
|
// Get the initial default dir for holding all projects.
|
||||||
export async function getInitialDefaultDir(): Promise<string> {
|
export async function getInitialDefaultDir(): Promise<string> {
|
||||||
if (!isTauri()) {
|
if (!isDesktop()) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
return invoke<string>('get_initial_default_dir')
|
return invoke<string>('get_initial_default_dir')
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function showInFolder(path: string | undefined): Promise<void> {
|
export async function showInFolder(path: string | undefined): Promise<void> {
|
||||||
if (!isTauri()) {
|
if (!isDesktop()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!path) {
|
if (!path) {
|
||||||
console.error('path is undefined cannot call tauri showInFolder')
|
console.error('path is undefined cannot call desktop showInFolder')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return await invoke('show_in_folder', { path })
|
return window.electron.ipcRenderer.invoke('show_in_folder', { path })
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function initializeProjectDirectory(
|
export async function initializeProjectDirectory(
|
||||||
settings: Configuration
|
settings: Configuration
|
||||||
): Promise<string | undefined> {
|
): Promise<string | undefined> {
|
||||||
if (!isTauri()) {
|
if (!isDesktop()) {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
return await invoke<string>('initialize_project_directory', {
|
return window.electron.ipcRenderer.invoke('initialize_project_directory', {
|
||||||
configuration: settings,
|
configuration: settings,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -85,7 +86,7 @@ export async function createNewProjectDirectory(
|
|||||||
if (!configuration) {
|
if (!configuration) {
|
||||||
configuration = await readAppSettingsFile()
|
configuration = await readAppSettingsFile()
|
||||||
}
|
}
|
||||||
return await invoke<Project>('create_new_project_directory', {
|
return window.electron.ipcRenderer.invoke('create_new_project_directory', {
|
||||||
configuration,
|
configuration,
|
||||||
projectName,
|
projectName,
|
||||||
initialCode,
|
initialCode,
|
||||||
@ -98,7 +99,7 @@ export async function listProjects(
|
|||||||
if (!configuration) {
|
if (!configuration) {
|
||||||
configuration = await readAppSettingsFile()
|
configuration = await readAppSettingsFile()
|
||||||
}
|
}
|
||||||
return await invoke<Project[]>('list_projects', { configuration })
|
return window.electron.ipcRenderer.invoke('list_projects', { configuration })
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getProjectInfo(
|
export async function getProjectInfo(
|
||||||
@ -108,21 +109,21 @@ export async function getProjectInfo(
|
|||||||
if (!configuration) {
|
if (!configuration) {
|
||||||
configuration = await readAppSettingsFile()
|
configuration = await readAppSettingsFile()
|
||||||
}
|
}
|
||||||
return await invoke<Project>('get_project_info', {
|
return window.electron.ipcRenderer.invoke('get_project_info', {
|
||||||
configuration,
|
configuration,
|
||||||
projectPath,
|
projectPath,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function login(host: string): Promise<string> {
|
export async function login(host: string): Promise<string> {
|
||||||
return await invoke('login', { host })
|
return window.electron.ipcRenderer.invoke('login', { host })
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function parseProjectRoute(
|
export async function parseProjectRoute(
|
||||||
configuration: Configuration,
|
configuration: Configuration,
|
||||||
route: string
|
route: string
|
||||||
): Promise<ProjectRoute> {
|
): Promise<ProjectRoute> {
|
||||||
return await invoke<ProjectRoute>('parse_project_route', {
|
return window.electron.ipcRenderer.invoke('parse_project_route', {
|
||||||
configuration,
|
configuration,
|
||||||
route,
|
route,
|
||||||
})
|
})
|
||||||
@ -133,11 +134,11 @@ export async function getUser(
|
|||||||
host: string
|
host: string
|
||||||
): Promise<Models['User_type'] | Record<'error_code', unknown> | void> {
|
): Promise<Models['User_type'] | Record<'error_code', unknown> | void> {
|
||||||
if (!token) {
|
if (!token) {
|
||||||
console.error('token is undefined cannot call tauri getUser')
|
console.error('token is undefined cannot call desktop getUser')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return await invoke<Models['User_type'] | Record<'error_code', unknown>>(
|
return window.electron.ipcRenderer.invoke>(
|
||||||
'get_user',
|
'get_user',
|
||||||
{
|
{
|
||||||
token: token,
|
token: token,
|
||||||
@ -147,26 +148,26 @@ export async function getUser(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function readDirRecursive(path: string): Promise<FileEntry[]> {
|
export async function readDirRecursive(path: string): Promise<FileEntry[]> {
|
||||||
return await invoke<FileEntry[]>('read_dir_recursive', { path })
|
return window.electron.ipcRenderer.invoke('read_dir_recursive', { path })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read the contents of the app settings.
|
// Read the contents of the app settings.
|
||||||
export async function readAppSettingsFile(): Promise<Configuration> {
|
export async function readAppSettingsFile(): Promise<Configuration> {
|
||||||
return await invoke<Configuration>('read_app_settings_file')
|
return window.electron.ipcRenderer.invoke('read_app_settings_file')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the contents of the app settings.
|
// Write the contents of the app settings.
|
||||||
export async function writeAppSettingsFile(
|
export async function writeAppSettingsFile(
|
||||||
settings: Configuration
|
settings: Configuration
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return await invoke('write_app_settings_file', { configuration: settings })
|
return window.electron.ipcRenderer.invoke('write_app_settings_file', { configuration: settings })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read project settings file.
|
// Read project settings file.
|
||||||
export async function readProjectSettingsFile(
|
export async function readProjectSettingsFile(
|
||||||
projectPath: string
|
projectPath: string
|
||||||
): Promise<ProjectConfiguration> {
|
): Promise<ProjectConfiguration> {
|
||||||
return await invoke<ProjectConfiguration>('read_project_settings_file', {
|
return window.electron.ipcRenderer.invoke('read_project_settings_file', {
|
||||||
projectPath,
|
projectPath,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -176,7 +177,7 @@ export async function writeProjectSettingsFile(
|
|||||||
projectPath: string,
|
projectPath: string,
|
||||||
settings: ProjectConfiguration
|
settings: ProjectConfiguration
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return await invoke('write_project_settings_file', {
|
return window.electron.ipcRenderer.invoke('write_project_settings_file', {
|
||||||
projectPath,
|
projectPath,
|
||||||
configuration: settings,
|
configuration: settings,
|
||||||
})
|
})
|
8
src/lib/electron.ts
Normal file
8
src/lib/electron.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { app, ipcMain } from 'electron'
|
||||||
|
|
||||||
|
const DEFAULT_HOST = "https://api.zoo.dev"
|
||||||
|
const SETTINGS_FILE_NAME = "settings.toml"
|
||||||
|
const PROJECT_SETTINGS_FILE_NAME = "project.toml"
|
||||||
|
const PROJECT_FOLDER = "zoo-modeling-app-projects"
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
import { isTauri } from './isTauri'
|
import { isDesktop } from './isDesktop'
|
||||||
import { deserialize_files } from '../wasm-lib/pkg/wasm_lib'
|
import { deserialize_files } from '../wasm-lib/pkg/wasm_lib'
|
||||||
import { browserSaveFile } from './browserSaveFile'
|
import { browserSaveFile } from './browserSaveFile'
|
||||||
import { save } from '@tauri-apps/plugin-dialog'
|
import { save } from '@tauri-apps/plugin-dialog'
|
||||||
@ -9,7 +9,7 @@ import ModelingAppFile from './modelingAppFile'
|
|||||||
|
|
||||||
const save_ = async (file: ModelingAppFile) => {
|
const save_ = async (file: ModelingAppFile) => {
|
||||||
try {
|
try {
|
||||||
if (isTauri()) {
|
if (isDesktop()) {
|
||||||
const extension = file.name.split('.').pop() || null
|
const extension = file.name.split('.').pop() || null
|
||||||
let extensions: string[] = []
|
let extensions: string[] = []
|
||||||
if (extension !== null) {
|
if (extension !== null) {
|
||||||
|
18
src/lib/fs.ts
Normal file
18
src/lib/fs.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
const { app, ipcMain } = require('electron')
|
||||||
|
const path = require('node:path')
|
||||||
|
const fs = require('node:fs')
|
||||||
|
|
||||||
|
app.whenReady().then(() => {
|
||||||
|
ipcMain.handle('readFile', async (event) => {
|
||||||
|
return fs.readFile(event.data[0], 'utf-8')
|
||||||
|
})
|
||||||
|
ipcMain.handle('readdir', async (event) => {
|
||||||
|
return fs.readdir(event.data[0], 'utf-8')
|
||||||
|
})
|
||||||
|
ipcMain.handle('join', async (event) => {
|
||||||
|
return path.join(event.data[0])
|
||||||
|
})
|
||||||
|
ipcMain.handle('exists', async (event) => {
|
||||||
|
return fs.exists(event.data[0])
|
||||||
|
})
|
||||||
|
})
|
5
src/lib/isDesktop.ts
Normal file
5
src/lib/isDesktop.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// https://github.com/electron/electron/issues/2288#issuecomment-337858978
|
||||||
|
// Thank you
|
||||||
|
export function isDesktop(): boolean {
|
||||||
|
return navigator.userAgent.toLowerCase().indexOf("electron") > -1;
|
||||||
|
}
|
@ -1,6 +0,0 @@
|
|||||||
export function isTauri(): boolean {
|
|
||||||
if (globalThis.window && typeof globalThis.window !== 'undefined') {
|
|
||||||
return '__TAURI_INTERNALS__' in globalThis.window
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
@ -1,9 +1,9 @@
|
|||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { open as tauriOpen } from '@tauri-apps/plugin-shell'
|
import { open as tauriOpen } from '@tauri-apps/plugin-shell'
|
||||||
|
|
||||||
// Open a new browser window tauri style or browser style.
|
// Open a new browser window tauri style or browser style.
|
||||||
export default async function openWindow(url: string) {
|
export default async function openWindow(url: string) {
|
||||||
if (isTauri()) {
|
if (isDesktop()) {
|
||||||
await tauriOpen(url)
|
await tauriOpen(url)
|
||||||
} else {
|
} else {
|
||||||
window.open(url, '_blank')
|
window.open(url, '_blank')
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||||
import { BROWSER_FILE_NAME, BROWSER_PROJECT_NAME, FILE_EXT } from './constants'
|
import { BROWSER_FILE_NAME, BROWSER_PROJECT_NAME, FILE_EXT } from './constants'
|
||||||
import { isTauri } from './isTauri'
|
import { isDesktop } from './isDesktop'
|
||||||
import { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
|
import { Configuration } from 'wasm-lib/kcl/bindings/Configuration'
|
||||||
import { ProjectRoute } from 'wasm-lib/kcl/bindings/ProjectRoute'
|
import { ProjectRoute } from 'wasm-lib/kcl/bindings/ProjectRoute'
|
||||||
import { parseProjectRoute, readAppSettingsFile } from './tauri'
|
import { parseProjectRoute, readAppSettingsFile } from './tauri'
|
||||||
@ -38,7 +38,7 @@ export async function getProjectMetaByRouteId(
|
|||||||
): Promise<ProjectRoute | undefined> {
|
): Promise<ProjectRoute | undefined> {
|
||||||
if (!id) return undefined
|
if (!id) return undefined
|
||||||
|
|
||||||
const inTauri = isTauri()
|
const inTauri = isDesktop()
|
||||||
|
|
||||||
if (configuration === undefined) {
|
if (configuration === undefined) {
|
||||||
configuration = inTauri
|
configuration = inTauri
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { ActionFunction, LoaderFunction, redirect } from 'react-router-dom'
|
import { ActionFunction, LoaderFunction, redirect } from 'react-router-dom'
|
||||||
import { FileLoaderData, HomeLoaderData, IndexLoaderData } from './types'
|
import { FileLoaderData, HomeLoaderData, IndexLoaderData } from './types'
|
||||||
import { isTauri } from './isTauri'
|
import { isDesktop } from './isDesktop'
|
||||||
import { getProjectMetaByRouteId, paths } from './paths'
|
import { getProjectMetaByRouteId, paths } from './paths'
|
||||||
import { BROWSER_PATH } from 'lib/paths'
|
import { BROWSER_PATH } from 'lib/paths'
|
||||||
import {
|
import {
|
||||||
@ -90,7 +90,7 @@ export const fileLoader: LoaderFunction = async ({
|
|||||||
if (!current_file_name || !current_file_path || !project_name) {
|
if (!current_file_name || !current_file_path || !project_name) {
|
||||||
return redirect(
|
return redirect(
|
||||||
`${paths.FILE}/${encodeURIComponent(
|
`${paths.FILE}/${encodeURIComponent(
|
||||||
`${params.id}${isTauri() ? sep() : '/'}${PROJECT_ENTRYPOINT}`
|
`${params.id}${isDesktop() ? sep() : '/'}${PROJECT_ENTRYPOINT}`
|
||||||
)}`
|
)}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -114,7 +114,7 @@ export const fileLoader: LoaderFunction = async ({
|
|||||||
|
|
||||||
const projectData: IndexLoaderData = {
|
const projectData: IndexLoaderData = {
|
||||||
code,
|
code,
|
||||||
project: isTauri()
|
project: isDesktop()
|
||||||
? await getProjectInfo(project_path, configuration)
|
? await getProjectInfo(project_path, configuration)
|
||||||
: {
|
: {
|
||||||
name: project_name,
|
name: project_name,
|
||||||
@ -157,7 +157,7 @@ export const fileLoader: LoaderFunction = async ({
|
|||||||
export const homeLoader: LoaderFunction = async (): Promise<
|
export const homeLoader: LoaderFunction = async (): Promise<
|
||||||
HomeLoaderData | Response
|
HomeLoaderData | Response
|
||||||
> => {
|
> => {
|
||||||
if (!isTauri()) {
|
if (!isDesktop()) {
|
||||||
return redirect(paths.FILE + '/%2F' + BROWSER_PROJECT_NAME)
|
return redirect(paths.FILE + '/%2F' + BROWSER_PROJECT_NAME)
|
||||||
}
|
}
|
||||||
const { configuration } = await loadAndValidateSettings()
|
const { configuration } = await loadAndValidateSettings()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
|
|
||||||
export type InteractionMapItem = {
|
export type InteractionMapItem = {
|
||||||
name: string
|
name: string
|
||||||
@ -38,7 +38,7 @@ export const interactionMap: Record<
|
|||||||
Settings: [
|
Settings: [
|
||||||
{
|
{
|
||||||
name: 'toggle-settings',
|
name: 'toggle-settings',
|
||||||
sequence: isTauri() ? 'Meta+,' : 'Shift+Meta+,',
|
sequence: isDesktop() ? 'Meta+,' : 'Shift+Meta+,',
|
||||||
title: 'Toggle Settings',
|
title: 'Toggle Settings',
|
||||||
description: 'Opens the settings dialog. Always available.',
|
description: 'Opens the settings dialog. Always available.',
|
||||||
},
|
},
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
cameraMouseDragGuards,
|
cameraMouseDragGuards,
|
||||||
cameraSystems,
|
cameraSystems,
|
||||||
} from 'lib/cameraControls'
|
} from 'lib/cameraControls'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { useRef } from 'react'
|
import { useRef } from 'react'
|
||||||
import { open } from '@tauri-apps/plugin-dialog'
|
import { open } from '@tauri-apps/plugin-dialog'
|
||||||
import { CustomIcon } from 'components/CustomIcon'
|
import { CustomIcon } from 'components/CustomIcon'
|
||||||
@ -192,7 +192,7 @@ export function createSettings() {
|
|||||||
description: 'The directory to save and load projects from',
|
description: 'The directory to save and load projects from',
|
||||||
hideOnLevel: 'project',
|
hideOnLevel: 'project',
|
||||||
hideOnPlatform: 'web',
|
hideOnPlatform: 'web',
|
||||||
validate: (v) => typeof v === 'string' && (v.length > 0 || !isTauri()),
|
validate: (v) => typeof v === 'string' && (v.length > 0 || !isDesktop()),
|
||||||
Component: ({ value, updateValue }) => {
|
Component: ({ value, updateValue }) => {
|
||||||
const inputRef = useRef<HTMLInputElement>(null)
|
const inputRef = useRef<HTMLInputElement>(null)
|
||||||
return (
|
return (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Setting, createSettings, settings } from 'lib/settings/initialSettings'
|
import { Setting, createSettings, settings } from 'lib/settings/initialSettings'
|
||||||
import { SaveSettingsPayload, SettingsLevel } from './settingsTypes'
|
import { SaveSettingsPayload, SettingsLevel } from './settingsTypes'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { err } from 'lib/trap'
|
import { err } from 'lib/trap'
|
||||||
import {
|
import {
|
||||||
defaultAppSettings,
|
defaultAppSettings,
|
||||||
@ -18,7 +18,7 @@ import {
|
|||||||
readProjectSettingsFile,
|
readProjectSettingsFile,
|
||||||
writeAppSettingsFile,
|
writeAppSettingsFile,
|
||||||
writeProjectSettingsFile,
|
writeProjectSettingsFile,
|
||||||
} from 'lib/tauri'
|
} from 'lib/desktop'
|
||||||
import { ProjectConfiguration } from 'wasm-lib/kcl/bindings/ProjectConfiguration'
|
import { ProjectConfiguration } from 'wasm-lib/kcl/bindings/ProjectConfiguration'
|
||||||
import { BROWSER_PROJECT_NAME } from 'lib/constants'
|
import { BROWSER_PROJECT_NAME } from 'lib/constants'
|
||||||
|
|
||||||
@ -159,15 +159,15 @@ export async function loadAndValidateSettings(
|
|||||||
projectPath?: string
|
projectPath?: string
|
||||||
): Promise<AppSettings> {
|
): Promise<AppSettings> {
|
||||||
const settings = createSettings()
|
const settings = createSettings()
|
||||||
const inTauri = isTauri()
|
const onDesktop = isDesktop()
|
||||||
|
|
||||||
if (!inTauri) {
|
if (!onDesktop) {
|
||||||
// Make sure we have wasm initialized.
|
// Make sure we have wasm initialized.
|
||||||
await initPromise
|
await initPromise
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the app settings from the file system or localStorage.
|
// Load the app settings from the file system or localStorage.
|
||||||
const appSettings = inTauri
|
const appSettings = onDesktop
|
||||||
? await readAppSettingsFile()
|
? await readAppSettingsFile()
|
||||||
: readLocalStorageAppSettingsFile()
|
: readLocalStorageAppSettingsFile()
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ export async function loadAndValidateSettings(
|
|||||||
|
|
||||||
// Load the project settings if they exist
|
// Load the project settings if they exist
|
||||||
if (projectPath) {
|
if (projectPath) {
|
||||||
const projectSettings = inTauri
|
const projectSettings = onDesktop
|
||||||
? await readProjectSettingsFile(projectPath)
|
? await readProjectSettingsFile(projectPath)
|
||||||
: readLocalStorageProjectSettingsFile()
|
: readLocalStorageProjectSettingsFile()
|
||||||
|
|
||||||
@ -201,7 +201,7 @@ export async function saveSettings(
|
|||||||
) {
|
) {
|
||||||
// Make sure we have wasm initialized.
|
// Make sure we have wasm initialized.
|
||||||
await initPromise
|
await initPromise
|
||||||
const inTauri = isTauri()
|
const onDesktop = isDesktop()
|
||||||
|
|
||||||
// Get the user settings.
|
// Get the user settings.
|
||||||
const jsAppSettings = getChangedSettingsAtLevel(allSettings, 'user')
|
const jsAppSettings = getChangedSettingsAtLevel(allSettings, 'user')
|
||||||
@ -216,7 +216,7 @@ export async function saveSettings(
|
|||||||
if (err(tomlString2)) return
|
if (err(tomlString2)) return
|
||||||
|
|
||||||
// Write the app settings.
|
// Write the app settings.
|
||||||
if (inTauri) {
|
if (onDesktop) {
|
||||||
await writeAppSettingsFile(appSettings)
|
await writeAppSettingsFile(appSettings)
|
||||||
} else {
|
} else {
|
||||||
localStorage.setItem(localStorageAppSettingsPath(), tomlString2)
|
localStorage.setItem(localStorageAppSettingsPath(), tomlString2)
|
||||||
@ -241,7 +241,7 @@ export async function saveSettings(
|
|||||||
if (err(tomlStr)) return
|
if (err(tomlStr)) return
|
||||||
|
|
||||||
// Write the project settings.
|
// Write the project settings.
|
||||||
if (inTauri) {
|
if (onDesktop) {
|
||||||
await writeProjectSettingsFile(projectPath, projectSettings)
|
await writeProjectSettingsFile(projectPath, projectSettings)
|
||||||
} else {
|
} else {
|
||||||
localStorage.setItem(localStorageProjectSettingsPath(), tomlStr)
|
localStorage.setItem(localStorageProjectSettingsPath(), tomlStr)
|
||||||
@ -315,7 +315,7 @@ export function shouldHideSetting(
|
|||||||
return (
|
return (
|
||||||
setting.hideOnLevel === settingsLevel ||
|
setting.hideOnLevel === settingsLevel ||
|
||||||
setting.hideOnPlatform === 'both' ||
|
setting.hideOnPlatform === 'both' ||
|
||||||
(setting.hideOnPlatform && isTauri()
|
(setting.hideOnPlatform && isDesktop()
|
||||||
? setting.hideOnPlatform === 'desktop'
|
? setting.hideOnPlatform === 'desktop'
|
||||||
: setting.hideOnPlatform === 'web')
|
: setting.hideOnPlatform === 'web')
|
||||||
)
|
)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { appConfigDir } from '@tauri-apps/api/path'
|
import { appConfigDir } from '@tauri-apps/api/path'
|
||||||
import { isTauri } from './isTauri'
|
import { isDesktop } from './isDesktop'
|
||||||
import type { FileEntry } from 'lib/types'
|
import type { FileEntry } from 'lib/types'
|
||||||
import {
|
import {
|
||||||
INDEX_IDENTIFIER,
|
INDEX_IDENTIFIER,
|
||||||
@ -108,7 +108,7 @@ function getPaddedIdentifierRegExp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function getSettingsFolderPaths(projectPath?: string) {
|
export async function getSettingsFolderPaths(projectPath?: string) {
|
||||||
const user = isTauri() ? await appConfigDir() : '/'
|
const user = isDesktop() ? await appConfigDir() : '/'
|
||||||
const project = projectPath !== undefined ? projectPath : undefined
|
const project = projectPath !== undefined ? projectPath : undefined
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createMachine, assign } from 'xstate'
|
import { createMachine, assign } from 'xstate'
|
||||||
import { Models } from '@kittycad/lib'
|
import { Models } from '@kittycad/lib'
|
||||||
import withBaseURL from '../lib/withBaseURL'
|
import withBaseURL from '../lib/withBaseURL'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { VITE_KC_API_BASE_URL, VITE_KC_DEV_TOKEN } from 'env'
|
import { VITE_KC_API_BASE_URL, VITE_KC_DEV_TOKEN } from 'env'
|
||||||
import { getUser as getUserTauri } from 'lib/tauri'
|
import { getUser as getUserTauri } from 'lib/tauri'
|
||||||
|
|
||||||
@ -123,7 +123,7 @@ async function getUser(context: UserContext) {
|
|||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!token && isTauri()) return Promise.reject(new Error('No token found'))
|
if (!token && isDesktop()) return Promise.reject(new Error('No token found'))
|
||||||
if (token) headers['Authorization'] = `Bearer ${context.token}`
|
if (token) headers['Authorization'] = `Bearer ${context.token}`
|
||||||
|
|
||||||
if (SKIP_AUTH) {
|
if (SKIP_AUTH) {
|
||||||
@ -138,7 +138,7 @@ async function getUser(context: UserContext) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const userPromise = !isTauri()
|
const userPromise = !isDesktop()
|
||||||
? fetch(url, {
|
? fetch(url, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
@ -164,7 +164,7 @@ async function getUser(context: UserContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getCookie(cname: string): string | null {
|
function getCookie(cname: string): string | null {
|
||||||
if (isTauri()) {
|
if (isDesktop()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import { app, BrowserWindow } from 'electron'
|
import { app, BrowserWindow } from 'electron'
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
|
import 'lib/fs'
|
||||||
|
|
||||||
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
|
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
|
||||||
if (require('electron-squirrel-startup')) {
|
if (require('electron-squirrel-startup')) {
|
||||||
@ -41,3 +42,4 @@ app.on('window-all-closed', () => {
|
|||||||
// initialization and is ready to create browser windows.
|
// initialization and is ready to create browser windows.
|
||||||
// Some APIs can only be used after this event occurs.
|
// Some APIs can only be used after this event occurs.
|
||||||
app.on('ready', createWindow)
|
app.on('ready', createWindow)
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ import { useCommandsContext } from 'hooks/useCommandsContext'
|
|||||||
import { join, 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 { isDesktop } from 'lib/isDesktop'
|
||||||
import { kclManager } from 'lib/singletons'
|
import { kclManager } from 'lib/singletons'
|
||||||
import { useLspContext } from 'components/LspProvider'
|
import { useLspContext } from 'components/LspProvider'
|
||||||
import { useRefreshSettings } from 'hooks/useRefreshSettings'
|
import { useRefreshSettings } from 'hooks/useRefreshSettings'
|
||||||
@ -38,7 +38,7 @@ import {
|
|||||||
createNewProjectDirectory,
|
createNewProjectDirectory,
|
||||||
listProjects,
|
listProjects,
|
||||||
renameProjectDirectory,
|
renameProjectDirectory,
|
||||||
} from 'lib/tauri'
|
} from 'lib/desktop'
|
||||||
import { ProjectSearchBar, useProjectSearch } from 'components/ProjectSearchBar'
|
import { ProjectSearchBar, useProjectSearch } from 'components/ProjectSearchBar'
|
||||||
|
|
||||||
// This route only opens in the Tauri desktop context for now,
|
// This route only opens in the Tauri desktop context for now,
|
||||||
@ -62,7 +62,7 @@ const Home = () => {
|
|||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
})
|
})
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
isTauri() ? 'mod+,' : 'shift+mod+,',
|
isDesktop() ? 'mod+,' : 'shift+mod+,',
|
||||||
() => navigate(paths.HOME + paths.SETTINGS),
|
() => navigate(paths.HOME + paths.SETTINGS),
|
||||||
{
|
{
|
||||||
splitKey: '|',
|
splitKey: '|',
|
||||||
|
@ -4,8 +4,9 @@ import { useSettingsAuthContext } from 'hooks/useSettingsAuthContext'
|
|||||||
import { Themes, getSystemTheme } from 'lib/theme'
|
import { Themes, getSystemTheme } from 'lib/theme'
|
||||||
import { bracket } from 'lib/exampleKcl'
|
import { bracket } from 'lib/exampleKcl'
|
||||||
import { createAndOpenNewProject } from 'lib/tauriFS'
|
import { createAndOpenNewProject } from 'lib/tauriFS'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { useNavigate, useRouteLoaderData } from 'react-router-dom'
|
import { useNavigate, useRouteLoaderData } from 'react-router-dom'
|
||||||
|
import { paths } from 'lib/paths'
|
||||||
import { codeManager, kclManager } from 'lib/singletons'
|
import { codeManager, kclManager } from 'lib/singletons'
|
||||||
import { APP_NAME } from 'lib/constants'
|
import { APP_NAME } from 'lib/constants'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { OnboardingButtons, useDismiss, useNextClick } from '.'
|
import { OnboardingButtons, useDismiss, useNextClick } from '.'
|
||||||
import { onboardingPaths } from 'routes/Onboarding/paths'
|
import { onboardingPaths } from 'routes/Onboarding/paths'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
import { useModelingContext } from 'hooks/useModelingContext'
|
import { useModelingContext } from 'hooks/useModelingContext'
|
||||||
|
|
||||||
export default function ProjectMenu() {
|
export default function ProjectMenu() {
|
||||||
const { context } = useModelingContext()
|
const { context } = useModelingContext()
|
||||||
const dismiss = useDismiss()
|
const dismiss = useDismiss()
|
||||||
const next = useNextClick(onboardingPaths.EXPORT)
|
const next = useNextClick(onboardingPaths.EXPORT)
|
||||||
const tauri = isTauri()
|
const tauri = isDesktop()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="fixed grid justify-center items-start inset-0 z-50 pointer-events-none">
|
<div className="fixed grid justify-center items-start inset-0 z-50 pointer-events-none">
|
||||||
|
@ -12,9 +12,9 @@ import { SettingsSectionsList } from 'components/Settings/SettingsSectionsList'
|
|||||||
import { AllSettingsFields } from 'components/Settings/AllSettingsFields'
|
import { AllSettingsFields } from 'components/Settings/AllSettingsFields'
|
||||||
import { AllKeybindingsFields } from 'components/Settings/AllKeybindingsFields'
|
import { AllKeybindingsFields } from 'components/Settings/AllKeybindingsFields'
|
||||||
import { KeybindingsSectionsList } from 'components/Settings/KeybindingsSectionsList'
|
import { KeybindingsSectionsList } from 'components/Settings/KeybindingsSectionsList'
|
||||||
import { isTauri } from 'lib/isTauri'
|
import { isDesktop } from 'lib/isDesktop'
|
||||||
|
|
||||||
export const APP_VERSION = isTauri()
|
export const APP_VERSION = isDesktop()
|
||||||
? import.meta.env.PACKAGE_VERSION || 'unknown'
|
? import.meta.env.PACKAGE_VERSION || 'unknown'
|
||||||
: 'main'
|
: 'main'
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { ActionButton } from '../components/ActionButton'
|
import { ActionButton } from '../components/ActionButton'
|
||||||
import { isTauri } from '../lib/isTauri'
|
import { isDesktop } from '../lib/isDesktop'
|
||||||
import { VITE_KC_SITE_BASE_URL, VITE_KC_API_BASE_URL } from '../env'
|
import { VITE_KC_SITE_BASE_URL, VITE_KC_API_BASE_URL } from '../env'
|
||||||
import { Themes, getSystemTheme } from '../lib/theme'
|
import { Themes, getSystemTheme } from '../lib/theme'
|
||||||
import { paths } from 'lib/paths'
|
import { paths } from 'lib/paths'
|
||||||
@ -61,7 +61,7 @@ const SignIn = () => {
|
|||||||
ZMA is ready for production, please sign up for our mailing list at{' '}
|
ZMA is ready for production, please sign up for our mailing list at{' '}
|
||||||
<a href="https://zoo.dev">zoo.dev</a>.
|
<a href="https://zoo.dev">zoo.dev</a>.
|
||||||
</p>
|
</p>
|
||||||
{isTauri() ? (
|
{isDesktop() ? (
|
||||||
<ActionButton
|
<ActionButton
|
||||||
Element="button"
|
Element="button"
|
||||||
onClick={signInTauri}
|
onClick={signInTauri}
|
||||||
|
@ -47,7 +47,7 @@ impl CoreDump for CoreDumper {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_tauri(&self) -> Result<bool> {
|
fn is_desktop(&self) -> Result<bool> {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ pub trait CoreDump: Clone {
|
|||||||
|
|
||||||
async fn os(&self) -> Result<OsInfo>;
|
async fn os(&self) -> Result<OsInfo>;
|
||||||
|
|
||||||
fn is_tauri(&self) -> Result<bool>;
|
fn is_desktop(&self) -> Result<bool>;
|
||||||
|
|
||||||
async fn get_webrtc_stats(&self) -> Result<WebrtcStats>;
|
async fn get_webrtc_stats(&self) -> Result<WebrtcStats>;
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ pub trait CoreDump: Clone {
|
|||||||
version: self.version()?,
|
version: self.version()?,
|
||||||
git_rev: git_rev::try_revision_string!().map_or_else(|| "unknown".to_string(), |s| s.to_string()),
|
git_rev: git_rev::try_revision_string!().map_or_else(|| "unknown".to_string(), |s| s.to_string()),
|
||||||
timestamp: chrono::Utc::now(),
|
timestamp: chrono::Utc::now(),
|
||||||
tauri: self.is_tauri()?,
|
tauri: self.is_desktop()?,
|
||||||
os,
|
os,
|
||||||
webrtc_stats,
|
webrtc_stats,
|
||||||
github_issue_url: None,
|
github_issue_url: None,
|
||||||
|
@ -26,8 +26,8 @@ extern "C" {
|
|||||||
#[wasm_bindgen(method, js_name = getOsInfo, catch)]
|
#[wasm_bindgen(method, js_name = getOsInfo, catch)]
|
||||||
fn get_os_info(this: &CoreDumpManager) -> Result<js_sys::Promise, js_sys::Error>;
|
fn get_os_info(this: &CoreDumpManager) -> Result<js_sys::Promise, js_sys::Error>;
|
||||||
|
|
||||||
#[wasm_bindgen(method, js_name = isTauri, catch)]
|
#[wasm_bindgen(method, js_name = isDesktop, catch)]
|
||||||
fn is_tauri(this: &CoreDumpManager) -> Result<bool, js_sys::Error>;
|
fn is_desktop(this: &CoreDumpManager) -> Result<bool, js_sys::Error>;
|
||||||
|
|
||||||
#[wasm_bindgen(method, js_name = getWebrtcStats, catch)]
|
#[wasm_bindgen(method, js_name = getWebrtcStats, catch)]
|
||||||
fn get_webrtc_stats(this: &CoreDumpManager) -> Result<js_sys::Promise, js_sys::Error>;
|
fn get_webrtc_stats(this: &CoreDumpManager) -> Result<js_sys::Promise, js_sys::Error>;
|
||||||
@ -100,9 +100,9 @@ impl CoreDump for CoreDumper {
|
|||||||
Ok(os)
|
Ok(os)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_tauri(&self) -> Result<bool> {
|
fn is_desktop(&self) -> Result<bool> {
|
||||||
self.manager
|
self.manager
|
||||||
.is_tauri()
|
.is_desktop()
|
||||||
.map_err(|e| anyhow::anyhow!("Failed to get response from is tauri: {:?}", e))
|
.map_err(|e| anyhow::anyhow!("Failed to get response from is tauri: {:?}", e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user