diff --git a/src/common/stores/workspace/WorkspaceLiveFilePicker.tsx b/src/common/stores/workspace/WorkspaceLiveFilePicker.tsx index 89adf49d7..e0451fc82 100644 --- a/src/common/stores/workspace/WorkspaceLiveFilePicker.tsx +++ b/src/common/stores/workspace/WorkspaceLiveFilePicker.tsx @@ -6,6 +6,7 @@ import CodeIcon from '@mui/icons-material/Code'; import type { LiveFileId, LiveFileMetadata } from '~/common/livefile/liveFile.types'; import { CloseableMenu } from '~/common/components/CloseableMenu'; +import { LiveFileChooseIcon } from '~/common/livefile/liveFile.icons'; import { LiveFilePatchIcon } from '~/common/components/icons/LiveFilePatchIcon'; import { useContextWorkspaceId } from './WorkspaceIdProvider'; @@ -25,6 +26,7 @@ export function WorkspaceLiveFilePicker(props: { liveFileId: LiveFileId | null; allowRemove?: boolean; onSelectLiveFile: (id: LiveFileId | null) => void; + onSelectNewFile?: () => void; // tooltipLabel?: string; }) { @@ -37,7 +39,7 @@ export function WorkspaceLiveFilePicker(props: { // set as disabled when empty const haveLiveFiles = wLiveFiles.length > 0; - const { autoSelectName, liveFileId, onSelectLiveFile } = props; + const { autoSelectName, liveFileId, onSelectLiveFile, onSelectNewFile } = props; // [effect] auto-select a LiveFileId @@ -73,6 +75,13 @@ export function WorkspaceLiveFilePicker(props: { setMenuAnchor(null); }, [onSelectLiveFile]); + const handleSelectNewFile = React.useCallback(() => { + if (onSelectNewFile) { + onSelectNewFile(); + setMenuAnchor(null); + } + }, [onSelectNewFile]); + // Note: in the future let this be, we can show a file picker that adds LiveFiles to the workspace // if (!haveLiveFiles) @@ -122,16 +131,16 @@ export function WorkspaceLiveFilePicker(props: { > {/* Workspace Files (if any) */} - {haveLiveFiles && ( - - Select Target: - - )} + + Select Target: + + {haveLiveFiles && wLiveFiles.map((lfm: LiveFileMetadata) => ( handleSelectLiveFile(lfm.id)} + sx={{ border: 'none' }} > @@ -144,10 +153,13 @@ export function WorkspaceLiveFilePicker(props: { ))} {/* Pair a new file */} - {!haveLiveFiles && ( - - Add file picker here?s - + {!!props.onSelectNewFile && ( + + + + + Other target file... + )} {/* Remove pairing */} diff --git a/src/modules/blocks/enhanced-code/livefile-patch/useLiveFilePatch.tsx b/src/modules/blocks/enhanced-code/livefile-patch/useLiveFilePatch.tsx index 1c876d163..9e82a0f6d 100644 --- a/src/modules/blocks/enhanced-code/livefile-patch/useLiveFilePatch.tsx +++ b/src/modules/blocks/enhanced-code/livefile-patch/useLiveFilePatch.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import { Box, Button, Typography } from '@mui/joy'; import type { LiveFileId } from '~/common/livefile/liveFile.types'; -import { isLiveFileSupported } from '~/common/livefile/store-live-file'; +import { isLiveFileSupported, liveFileCreateOrThrow } from '~/common/livefile/store-live-file'; import { useUXLabsStore } from '~/common/state/store-ux-labs'; import { WorkspaceLiveFilePicker } from '~/common/stores/workspace/WorkspaceLiveFilePicker'; @@ -26,11 +26,29 @@ export function useLiveFilePatch(title: string, code: string, isPartial: boolean setLiveFileId(id); }, []); + const handleSelectNewFile = React.useCallback(async () => { + try { + const fileHandle = await window.showSaveFilePicker({ + suggestedName: title, + // types: [{ description: 'Text Files', accept: { 'text/plain': ['.txt'] } }], + }); + const newLiveFileId = await liveFileCreateOrThrow(fileHandle); + setLiveFileId(newLiveFileId); + } catch (error) { + console.error('Error creating new file:', error); + } + }, [title]); + // components const button = React.useMemo(() => !isEnabled ? null : ( - + {/* Patch LiveFile */} {!!liveFileId && ( @@ -50,6 +68,7 @@ export function useLiveFilePatch(title: string, code: string, isPartial: boolean buttonLabel='Insert...' liveFileId={liveFileId} onSelectLiveFile={handleLiveFileSelected} + onSelectNewFile={handleSelectNewFile} />