LFS: pairing 1

This commit is contained in:
Enrico Ros
2024-08-07 13:42:10 -07:00
parent bd873b84c9
commit e07b5aa988
2 changed files with 44 additions and 33 deletions
+27 -12
View File
@@ -4,6 +4,7 @@ import { Box, Button, SvgIcon } from '@mui/joy';
import UploadFileRoundedIcon from '@mui/icons-material/UploadFileRounded';
import { TooltipOutlined } from '~/common/components/TooltipOutlined';
import { getDataTransferFilesOrPromises } from '~/common/util/fileSystemUtils';
import { useDragDropDataTransfer } from '~/common/components/useDragDropDataTransfer';
import { LiveFileChooseIcon, LiveFileIcon } from './liveFile.icons';
@@ -11,16 +12,30 @@ import { LiveFileChooseIcon, LiveFileIcon } from './liveFile.icons';
export function LiveFileSyncButton(props: {
disabled: boolean;
hasContent: boolean;
isPaired: boolean;
isRead: boolean;
handleSyncButtonClicked: () => void;
onPairWithFSFHandle: (fsHandle: FileSystemFileHandle) => Promise<any>;
onPairWithPicker: () => Promise<void>;
upUpdateFileContent: () => void;
}) {
const { onPairWithFSFHandle } = props;
const handleDataTransfer = React.useCallback(async (dataTransfer: DataTransfer) => {
// get FileSystemFileHandle objects from the DataTransfer
const fileOrFSHandlePromises = getDataTransferFilesOrPromises(dataTransfer.items, false);
if (!fileOrFSHandlePromises.length)
return;
console.log('LiveFileSyncButton: handleDataTransfer', dataTransfer);
}, []);
// resolve the promises to get the actual files/handles
const filesOrHandles = await Promise.all(fileOrFSHandlePromises);
for (let filesOrHandle of filesOrHandles) {
if (!(filesOrHandle instanceof File) && filesOrHandle?.kind === 'file' && filesOrHandle) {
await onPairWithFSFHandle(filesOrHandle);
break;
}
}
}, [onPairWithFSFHandle]);
const {
dragContainerSx,
@@ -38,27 +53,27 @@ export function LiveFileSyncButton(props: {
<TooltipOutlined
title={
props.isRead ? 'Click to reload the File and compare.'
props.hasContent ? 'Click to reload the File and compare.'
: props.isPaired ? 'Click to compare with the File contents.'
: 'Setup LiveFile pairing.'
}
color={props.isRead ? 'primary' : 'success'}
variant={props.isRead ? undefined : 'solid'}
color={props.hasContent ? 'primary' : 'success'}
variant={props.hasContent ? undefined : 'solid'}
>
<Button
variant='soft'
color={props.isRead ? 'primary' : 'success'}
color={props.hasContent ? 'primary' : 'success'}
size='sm'
disabled={props.disabled}
onClick={props.handleSyncButtonClicked}
onClick={props.isPaired ? props.upUpdateFileContent : props.onPairWithPicker}
startDecorator={
props.isRead ? <LiveFileIcon />
props.hasContent ? <LiveFileIcon />
: (props.isPaired ? <LiveFileIcon />
: <LiveFileChooseIcon />)
}
aria-label={props.isPaired ? 'Sync File' : 'Choose File'}
>
{props.isRead ? 'Refresh'
{props.hasContent ? 'Refresh'
: props.isPaired ? 'Sync File'
: 'Pair File'}
</Button>
+17 -21
View File
@@ -16,7 +16,6 @@ import { useLiveFile } from './liveFile.hooks';
import { LiveFileSyncButton } from '~/common/livefile/LiveFileSyncButton';
interface DiffSummary {
insertions: number;
deletions: number;
@@ -130,33 +129,28 @@ export function useLiveFileComparison(
}
}, [fileHasContent, isLoadingFile, reloadFileContent]);
const handlePairNewFileWithPicker = React.useCallback(async () => {
// Open the file picker
const fileWithHandle = await fileOpen({ description: 'Select a File to pair to this document' }).catch(() => null /* The User closed the files picker */);
if (!fileWithHandle)
return;
if (!fileWithHandle.handle) {
setStatus({ message: 'Browser does not support LiveFile operations.', mtype: 'error' });
return;
}
const handlePairNewFSFHandle = React.useCallback(async (fsfHandle: FileSystemFileHandle) => {
// Pair the file: create a LiveFile, replace it in the Fragment, and load the preview
try {
const liveFileId = await liveFileCreateOrThrow(fileWithHandle.handle);
const liveFileId = await liveFileCreateOrThrow(fsfHandle);
replaceLiveFileId(liveFileId);
// Immediately load the preview on this ID
await handleUpdateFileContent(liveFileId);
} catch (error: any) {
setStatus({ message: `Error pairing the file: ${error?.message || typeof error === 'string' ? error : 'Unknown error'}`, mtype: 'error' });
}
}, [replaceLiveFileId, handleUpdateFileContent]);
}, [handleUpdateFileContent, replaceLiveFileId]);
const handleSyncButtonClicked = React.useCallback(async () => {
if (isPairingValid)
await handleUpdateFileContent();
const handlePairNewFileWithPicker = React.useCallback(async () => {
// Open the file picker
const fileWithHandle = await fileOpen({ description: 'Select a File to pair to this document' }).catch(() => null /* The User closed the files picker */);
if (!fileWithHandle)
return;
if (fileWithHandle.handle)
await handlePairNewFSFHandle(fileWithHandle.handle);
else
await handlePairNewFileWithPicker();
}, [handlePairNewFileWithPicker, handleUpdateFileContent, isPairingValid]);
setStatus({ message: 'Browser does not support LiveFile operations.', mtype: 'error' });
}, [handlePairNewFSFHandle]);
// Save and Load from Disk
@@ -188,10 +182,12 @@ export function useLiveFileComparison(
<LiveFileSyncButton
disabled={isSavingFile}
isPaired={isPairingValid}
isRead={fileHasContent}
handleSyncButtonClicked={handleSyncButtonClicked}
hasContent={fileHasContent}
onPairWithFSFHandle={handlePairNewFSFHandle}
onPairWithPicker={handlePairNewFileWithPicker}
upUpdateFileContent={handleUpdateFileContent}
/>
), [fileHasContent, handleSyncButtonClicked, isPairingValid, isSavingFile]);
), [fileHasContent, handlePairNewFSFHandle, handlePairNewFileWithPicker, handleUpdateFileContent, isPairingValid, isSavingFile]);
const liveFileActionBox = React.useMemo(() => {
if (!status && !fileHasContent) return null;