2023-07-25 10:40:26 -04:00
|
|
|
import {
|
|
|
|
faArrowRotateBack,
|
|
|
|
faFolder,
|
|
|
|
faXmark,
|
|
|
|
} from '@fortawesome/free-solid-svg-icons'
|
2023-07-13 07:22:08 -04:00
|
|
|
import { ActionButton } from '../components/ActionButton'
|
|
|
|
import { AppHeader } from '../components/AppHeader'
|
|
|
|
import { open } from '@tauri-apps/api/dialog'
|
2023-08-09 13:57:07 -04:00
|
|
|
import { Themes, baseUnits, useStore } from '../useStore'
|
2023-08-08 12:39:11 -04:00
|
|
|
import { useRef } from 'react'
|
2023-07-13 07:22:08 -04:00
|
|
|
import { toast } from 'react-hot-toast'
|
2023-07-21 12:48:23 -04:00
|
|
|
import { Toggle } from '../components/Toggle/Toggle'
|
2023-07-25 10:40:26 -04:00
|
|
|
import { useNavigate } from 'react-router-dom'
|
2023-08-08 12:39:11 -04:00
|
|
|
import { useHotkeys } from 'react-hotkeys-hook'
|
2023-08-10 13:30:32 -04:00
|
|
|
import { paths } from '../Router'
|
2023-07-13 07:22:08 -04:00
|
|
|
|
|
|
|
export const Settings = () => {
|
2023-07-25 10:40:26 -04:00
|
|
|
const navigate = useNavigate()
|
2023-08-15 21:56:24 -04:00
|
|
|
useHotkeys('esc', () => navigate('../'))
|
2023-07-13 07:22:08 -04:00
|
|
|
const {
|
2023-08-08 12:39:11 -04:00
|
|
|
defaultDir,
|
|
|
|
setDefaultDir,
|
|
|
|
defaultProjectName,
|
|
|
|
setDefaultProjectName,
|
|
|
|
defaultUnitSystem,
|
|
|
|
setDefaultUnitSystem,
|
|
|
|
defaultBaseUnit,
|
|
|
|
setDefaultBaseUnit,
|
|
|
|
setDebugPanel,
|
|
|
|
debugPanel,
|
2023-07-31 06:33:10 -04:00
|
|
|
setOnboardingStatus,
|
2023-08-08 12:39:11 -04:00
|
|
|
theme,
|
|
|
|
setTheme,
|
2023-07-13 07:22:08 -04:00
|
|
|
} = useStore((s) => ({
|
|
|
|
defaultDir: s.defaultDir,
|
|
|
|
setDefaultDir: s.setDefaultDir,
|
|
|
|
defaultProjectName: s.defaultProjectName,
|
|
|
|
setDefaultProjectName: s.setDefaultProjectName,
|
2023-07-21 12:48:23 -04:00
|
|
|
defaultUnitSystem: s.defaultUnitSystem,
|
|
|
|
setDefaultUnitSystem: s.setDefaultUnitSystem,
|
|
|
|
defaultBaseUnit: s.defaultBaseUnit,
|
|
|
|
setDefaultBaseUnit: s.setDefaultBaseUnit,
|
2023-08-08 12:39:11 -04:00
|
|
|
setDebugPanel: s.setDebugPanel,
|
|
|
|
debugPanel: s.debugPanel,
|
2023-07-25 10:40:26 -04:00
|
|
|
setOnboardingStatus: s.setOnboardingStatus,
|
2023-07-31 06:33:10 -04:00
|
|
|
theme: s.theme,
|
|
|
|
setTheme: s.setTheme,
|
2023-07-13 07:22:08 -04:00
|
|
|
}))
|
2023-08-15 21:56:24 -04:00
|
|
|
const ogDefaultDir = useRef(defaultDir)
|
2023-08-08 12:39:11 -04:00
|
|
|
const ogDefaultProjectName = useRef(defaultProjectName)
|
2023-07-13 07:22:08 -04:00
|
|
|
|
|
|
|
async function handleDirectorySelection() {
|
|
|
|
const newDirectory = await open({
|
|
|
|
directory: true,
|
2023-08-10 13:30:32 -04:00
|
|
|
defaultPath: (defaultDir.base || '') + (defaultDir.dir || paths.INDEX),
|
2023-07-13 07:22:08 -04:00
|
|
|
title: 'Choose a new default directory',
|
|
|
|
})
|
|
|
|
|
|
|
|
if (newDirectory && newDirectory !== null && !Array.isArray(newDirectory)) {
|
|
|
|
setDefaultDir({ base: defaultDir.base, dir: newDirectory })
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
2023-08-10 13:30:32 -04:00
|
|
|
<div className="body-bg fixed inset-0 z-40 overflow-auto">
|
2023-07-13 07:22:08 -04:00
|
|
|
<AppHeader showToolbar={false}>
|
|
|
|
<ActionButton
|
2023-07-27 18:59:40 -04:00
|
|
|
Element="link"
|
2023-08-15 21:56:24 -04:00
|
|
|
to={'../'}
|
2023-07-13 07:22:08 -04:00
|
|
|
icon={{
|
|
|
|
icon: faXmark,
|
|
|
|
bgClassName: 'bg-destroy-80',
|
|
|
|
iconClassName:
|
|
|
|
'text-destroy-20 group-hover:text-destroy-10 hover:text-destroy-10',
|
|
|
|
}}
|
|
|
|
className="hover:border-destroy-40"
|
|
|
|
>
|
|
|
|
Close
|
|
|
|
</ActionButton>
|
|
|
|
</AppHeader>
|
2023-08-08 18:30:26 -04:00
|
|
|
<div className="my-24 max-w-5xl mx-auto">
|
2023-07-13 07:22:08 -04:00
|
|
|
<h1 className="text-4xl font-bold">User Settings</h1>
|
|
|
|
{(window as any).__TAURI__ && (
|
|
|
|
<SettingsSection
|
|
|
|
title="Default Directory"
|
|
|
|
description="Where newly-created projects are saved on your local computer"
|
|
|
|
>
|
|
|
|
<div className="w-full flex gap-4 p-1 rounded border border-chalkboard-30">
|
|
|
|
<input
|
|
|
|
className="flex-1 px-2 bg-transparent"
|
|
|
|
value={defaultDir.dir}
|
2023-08-08 12:39:11 -04:00
|
|
|
onChange={(e) => {
|
2023-07-13 07:22:08 -04:00
|
|
|
setDefaultDir({
|
2023-08-08 12:39:11 -04:00
|
|
|
base: defaultDir.base,
|
2023-07-13 07:22:08 -04:00
|
|
|
dir: e.target.value,
|
|
|
|
})
|
2023-08-15 21:56:24 -04:00
|
|
|
}}
|
|
|
|
onBlur={() => {
|
|
|
|
ogDefaultDir.current.dir !== defaultDir.dir &&
|
|
|
|
toast.success('Default directory updated')
|
|
|
|
ogDefaultDir.current.dir = defaultDir.dir
|
2023-08-08 12:39:11 -04:00
|
|
|
}}
|
2023-07-13 07:22:08 -04:00
|
|
|
/>
|
|
|
|
<ActionButton
|
2023-07-27 18:59:40 -04:00
|
|
|
Element="button"
|
2023-07-13 07:22:08 -04:00
|
|
|
className="bg-chalkboard-100 hover:bg-chalkboard-90 text-chalkboard-10 border-chalkboard-100 hover:border-chalkboard-70"
|
|
|
|
onClick={handleDirectorySelection}
|
|
|
|
icon={{
|
|
|
|
icon: faFolder,
|
|
|
|
bgClassName:
|
|
|
|
'bg-liquid-20 group-hover:bg-liquid-10 hover:bg-liquid-10',
|
|
|
|
iconClassName:
|
|
|
|
'text-liquid-90 group-hover:text-liquid-90 hover:text-liquid-90',
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
Choose a folder
|
|
|
|
</ActionButton>
|
|
|
|
</div>
|
|
|
|
</SettingsSection>
|
|
|
|
)}
|
|
|
|
<SettingsSection
|
|
|
|
title="Default Project Name"
|
|
|
|
description="Name template for new projects. Use $n to include an incrementing index"
|
|
|
|
>
|
|
|
|
<input
|
|
|
|
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
|
|
|
|
value={defaultProjectName}
|
2023-08-08 12:39:11 -04:00
|
|
|
onChange={(e) => {
|
|
|
|
setDefaultProjectName(e.target.value)
|
|
|
|
}}
|
|
|
|
onBlur={() => {
|
|
|
|
ogDefaultProjectName.current !== defaultProjectName &&
|
|
|
|
toast.success('Default project name updated')
|
2023-08-15 21:56:24 -04:00
|
|
|
ogDefaultProjectName.current = defaultProjectName
|
2023-08-08 12:39:11 -04:00
|
|
|
}}
|
2023-07-13 07:22:08 -04:00
|
|
|
/>
|
|
|
|
</SettingsSection>
|
2023-07-21 12:48:23 -04:00
|
|
|
<SettingsSection
|
|
|
|
title="Unit System"
|
|
|
|
description="Which unit system to use by default"
|
|
|
|
>
|
|
|
|
<Toggle
|
|
|
|
offLabel="Imperial"
|
|
|
|
onLabel="Metric"
|
|
|
|
name="settings-units"
|
|
|
|
checked={defaultUnitSystem === 'metric'}
|
2023-08-08 12:39:11 -04:00
|
|
|
onChange={(e) => {
|
|
|
|
const newUnitSystem = e.target.checked ? 'metric' : 'imperial'
|
|
|
|
setDefaultUnitSystem(newUnitSystem)
|
|
|
|
setDefaultBaseUnit(baseUnits[newUnitSystem][0])
|
|
|
|
toast.success('Unit system set to ' + newUnitSystem)
|
|
|
|
}}
|
2023-07-21 12:48:23 -04:00
|
|
|
/>
|
|
|
|
</SettingsSection>
|
|
|
|
<SettingsSection
|
|
|
|
title="Base Unit"
|
|
|
|
description="Which base unit to use in dimensions by default"
|
|
|
|
>
|
|
|
|
<select
|
|
|
|
id="base-unit"
|
|
|
|
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
|
|
|
|
value={defaultBaseUnit}
|
2023-08-08 12:39:11 -04:00
|
|
|
onChange={(e) => {
|
|
|
|
setDefaultBaseUnit(e.target.value)
|
|
|
|
toast.success('Base unit changed to ' + e.target.value)
|
|
|
|
}}
|
2023-07-21 12:48:23 -04:00
|
|
|
>
|
|
|
|
{baseUnits[defaultUnitSystem].map((unit) => (
|
|
|
|
<option key={unit} value={unit}>
|
|
|
|
{unit}
|
|
|
|
</option>
|
|
|
|
))}
|
|
|
|
</select>
|
|
|
|
</SettingsSection>
|
2023-07-21 16:53:06 +10:00
|
|
|
<SettingsSection
|
|
|
|
title="Debug Panel"
|
|
|
|
description="Show the debug panel in the editor"
|
|
|
|
>
|
2023-07-21 12:48:23 -04:00
|
|
|
<Toggle
|
|
|
|
name="settings-debug-panel"
|
2023-07-21 16:53:06 +10:00
|
|
|
checked={debugPanel}
|
2023-08-08 12:39:11 -04:00
|
|
|
onChange={(e) => {
|
|
|
|
setDebugPanel(e.target.checked)
|
|
|
|
toast.success(
|
|
|
|
'Debug panel toggled ' + (e.target.checked ? 'on' : 'off')
|
|
|
|
)
|
|
|
|
}}
|
2023-07-21 16:53:06 +10:00
|
|
|
/>
|
|
|
|
</SettingsSection>
|
2023-07-31 06:33:10 -04:00
|
|
|
<SettingsSection
|
|
|
|
title="Editor Theme"
|
|
|
|
description="Apply a light or dark theme to the editor"
|
|
|
|
>
|
2023-08-09 13:57:07 -04:00
|
|
|
<select
|
|
|
|
id="settings-theme"
|
|
|
|
className="block w-full px-3 py-1 border border-chalkboard-30 bg-transparent"
|
|
|
|
value={theme}
|
2023-08-08 12:39:11 -04:00
|
|
|
onChange={(e) => {
|
2023-08-09 13:57:07 -04:00
|
|
|
setTheme(e.target.value as Themes)
|
2023-08-08 12:39:11 -04:00
|
|
|
toast.success(
|
2023-08-09 13:57:07 -04:00
|
|
|
'Theme changed to ' +
|
|
|
|
e.target.value.slice(0, 1).toLocaleUpperCase() +
|
|
|
|
e.target.value.slice(1)
|
2023-08-08 12:39:11 -04:00
|
|
|
)
|
|
|
|
}}
|
2023-08-09 13:57:07 -04:00
|
|
|
>
|
|
|
|
{Object.entries(Themes).map(([label, value]) => (
|
|
|
|
<option key={value} value={value}>
|
|
|
|
{label}
|
|
|
|
</option>
|
|
|
|
))}
|
|
|
|
</select>
|
2023-07-31 06:33:10 -04:00
|
|
|
</SettingsSection>
|
2023-07-25 10:40:26 -04:00
|
|
|
<SettingsSection
|
|
|
|
title="Onboarding"
|
|
|
|
description="Replay the onboarding process"
|
|
|
|
>
|
|
|
|
<ActionButton
|
2023-08-15 21:56:24 -04:00
|
|
|
Element="button"
|
2023-07-25 10:40:26 -04:00
|
|
|
onClick={() => {
|
2023-07-31 06:33:10 -04:00
|
|
|
setOnboardingStatus('')
|
2023-08-15 21:56:24 -04:00
|
|
|
navigate('..' + paths.ONBOARDING.INDEX)
|
2023-07-25 10:40:26 -04:00
|
|
|
}}
|
|
|
|
icon={{ icon: faArrowRotateBack }}
|
|
|
|
>
|
|
|
|
Replay Onboarding
|
|
|
|
</ActionButton>
|
|
|
|
</SettingsSection>
|
2023-07-13 07:22:08 -04:00
|
|
|
</div>
|
2023-08-10 13:30:32 -04:00
|
|
|
</div>
|
2023-07-13 07:22:08 -04:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
interface SettingsSectionProps extends React.PropsWithChildren {
|
|
|
|
title: string
|
|
|
|
description?: string
|
|
|
|
}
|
|
|
|
|
2023-07-25 10:40:26 -04:00
|
|
|
export function SettingsSection({
|
2023-07-13 07:22:08 -04:00
|
|
|
title,
|
|
|
|
description,
|
|
|
|
children,
|
|
|
|
}: SettingsSectionProps) {
|
|
|
|
return (
|
2023-08-08 12:39:11 -04:00
|
|
|
<section className="my-16 last-of-type:mb-24 grid grid-cols-2 gap-12 items-start">
|
2023-07-13 07:22:08 -04:00
|
|
|
<div className="w-80">
|
|
|
|
<h2 className="text-2xl">{title}</h2>
|
|
|
|
<p className="mt-2 text-sm">{description}</p>
|
|
|
|
</div>
|
2023-07-21 12:48:23 -04:00
|
|
|
<div>{children}</div>
|
2023-07-13 07:22:08 -04:00
|
|
|
</section>
|
|
|
|
)
|
|
|
|
}
|