diff --git a/apps/studio/src/components/form-path-input.tsx b/apps/studio/src/components/form-path-input.tsx
new file mode 100644
index 0000000000..144e17b10c
--- /dev/null
+++ b/apps/studio/src/components/form-path-input.tsx
@@ -0,0 +1,61 @@
+import { useI18n } from '@wordpress/react-i18n';
+import FolderIcon from 'src/components/folder-icon';
+import { cx } from 'src/lib/cx';
+import { SiteFormError } from './site-form-error';
+
+export interface FormPathInputComponentProps {
+ value: string;
+ onClick: () => void;
+ error?: string;
+ tipMessage?: string;
+ id?: string;
+}
+
+export function FormPathInputComponent( {
+ value,
+ onClick,
+ error,
+ tipMessage,
+ id = 'site-path',
+}: FormPathInputComponentProps ) {
+ const { __ } = useI18n();
+ const errorId = `${ id }-error`;
+
+ return (
+
void } ) => {
const { __ } = useI18n();
@@ -44,6 +46,9 @@ export const PreferencesTab = ( { onClose }: { onClose: () => void } ) => {
const [ dirtyEditor, setDirtyEditor ] = useState< SupportedEditor | null >();
const [ dirtyTerminal, setDirtyTerminal ] = useState< SupportedTerminal >();
const [ dirtyIsCliInstalled, setDirtyIsCliInstalled ] = useState< boolean >();
+ const [ dirtyDefaultSiteDirectory, setDirtyDefaultSiteDirectory ] = useState< string >();
+ const [ defaultSiteDirectory, setDefaultSiteDirectory ] = useState< string >();
+ const [ isLoadingDefaultSiteDirectory, setIsLoadingDefaultSiteDirectory ] = useState( true );
const wasSavedRef = useRef( false );
const dirtyColorSchemeRef = useRef( dirtyColorScheme );
@@ -88,6 +93,9 @@ export const PreferencesTab = ( { onClose }: { onClose: () => void } ) => {
if ( dirtyIsCliInstalled !== undefined ) {
await saveCliIsInstalled( dirtyIsCliInstalled );
}
+ if ( dirtyDefaultSiteDirectory ) {
+ await getIpcApi().saveDefaultSiteDirectory( dirtyDefaultSiteDirectory );
+ }
onClose();
};
@@ -96,6 +104,7 @@ export const PreferencesTab = ( { onClose }: { onClose: () => void } ) => {
const editorSelection = dirtyEditor ?? editor ?? 'vscode';
const terminalSelection = dirtyTerminal ?? terminal ?? 'terminal';
const isCliInstalledSelection = dirtyIsCliInstalled ?? isCliInstalled ?? false;
+ const defaultSiteDirectorySelection = dirtyDefaultSiteDirectory ?? defaultSiteDirectory ?? '';
const hasChanges = [
[ dirtyColorScheme, colorScheme ],
@@ -103,8 +112,39 @@ export const PreferencesTab = ( { onClose }: { onClose: () => void } ) => {
[ dirtyEditor, editor ],
[ dirtyTerminal, terminal ],
[ dirtyIsCliInstalled, isCliInstalled ],
+ [ dirtyDefaultSiteDirectory, defaultSiteDirectory ],
].some( ( [ a, b ] ) => a !== undefined && a !== b );
+ useEffect( () => {
+ let isMounted = true;
+ void ( async () => {
+ try {
+ const directory = await getIpcApi().getDefaultSiteDirectory();
+ if ( ! isMounted ) {
+ return;
+ }
+ setDefaultSiteDirectory( directory );
+ } finally {
+ if ( isMounted ) {
+ setIsLoadingDefaultSiteDirectory( false );
+ }
+ }
+ } )();
+ return () => {
+ isMounted = false;
+ };
+ }, [] );
+
+ const handleChangeDefaultDirectory = async () => {
+ const response = await getIpcApi().showOpenFolderDialog(
+ __( 'Select default site directory' ),
+ defaultSiteDirectorySelection
+ );
+ if ( response?.path ) {
+ setDirtyDefaultSiteDirectory( response.path );
+ }
+ };
+
return (
<>
@@ -120,6 +160,14 @@ export const PreferencesTab = ( { onClose }: { onClose: () => void } ) => {
{ ! isWindowsStore() && (
) }
+
+
+