diff --git a/packages/upup/src/frontend/components/MainBox.tsx b/packages/upup/src/frontend/components/MainBox.tsx index 65ab111f..f84cbf7b 100644 --- a/packages/upup/src/frontend/components/MainBox.tsx +++ b/packages/upup/src/frontend/components/MainBox.tsx @@ -10,11 +10,15 @@ import AdapterView from './AdapterView' import FileList from './FileList' import MyAnimatePresence from './shared/MyAnimatePresence' import ShouldRender from './shared/ShouldRender' +import WarningAlert from './WarningAlert' + export default function MainBox() { const { files, activeAdapter, isAddingMore, + warningMessage, + clearWarning, props: { dark }, } = useRootContext() const { @@ -50,6 +54,13 @@ export default function MainBox() { onDragLeave={handleDragLeave} onDrop={handleDrop} > + + + diff --git a/packages/upup/src/frontend/components/WarningAlert.tsx b/packages/upup/src/frontend/components/WarningAlert.tsx new file mode 100644 index 00000000..f3a5dab5 --- /dev/null +++ b/packages/upup/src/frontend/components/WarningAlert.tsx @@ -0,0 +1,59 @@ +import { motion } from 'framer-motion' +import React from 'react' +import { TbAlertCircle, TbX } from 'react-icons/tb' +import { cn } from '../lib/tailwind' + +interface WarningAlertProps { + message: string + onClose: () => void + dark?: boolean +} + +export default function WarningAlert({ + message, + onClose, + dark = false, +}: WarningAlertProps) { + return ( + + +

+ {message} +

+ +
+ ) +} diff --git a/packages/upup/src/frontend/context/RootContext.ts b/packages/upup/src/frontend/context/RootContext.ts index b5afd38e..b87690ea 100644 --- a/packages/upup/src/frontend/context/RootContext.ts +++ b/packages/upup/src/frontend/context/RootContext.ts @@ -81,6 +81,8 @@ export interface IRootContext { googleDriveConfigs?: GoogleDriveConfigs dropboxConfigs?: DropboxConfigs upload: ContextUpload + warningMessage: string + clearWarning: () => void props: ContextProps } diff --git a/packages/upup/src/frontend/hooks/useRootProvider.ts b/packages/upup/src/frontend/hooks/useRootProvider.ts index 1cfa7bbf..8cbcbb8d 100644 --- a/packages/upup/src/frontend/hooks/useRootProvider.ts +++ b/packages/upup/src/frontend/hooks/useRootProvider.ts @@ -77,6 +77,7 @@ export default function useRootProvider({ {} as FilesProgressMap, ) const [uploadError, setUploadError] = useState('') + const [warningMessage, setWarningMessage] = useState('') // Keep a ref to selectedFilesMap for unmount cleanup const selectedFilesMapRef = useRef(selectedFilesMap) @@ -118,10 +119,16 @@ export default function useRootProvider({ const onWarn = useCallback( (message: string) => { + setWarningMessage(message) if (warningHandler) warningHandler(message) }, [warningHandler], ) + + const clearWarning = useCallback(() => { + setWarningMessage('') + }, []) + function isFileWithParamsArray( files: File[] | FileWithParams[], ): files is FileWithParams[] { @@ -166,11 +173,22 @@ export default function useRootProvider({ // Collect only the files that are actually accepted and added in this batch. const addedThisBatch: FileWithParams[] = [] + const totalSelectedFiles = newFiles.length for (const file of newFiles) { // Respect the limit strictly; stop when capacity is reached. if (newFilesMap.size >= limit) { - onWarn('Allowed limit has been surpassed!') + const remainingCount = + totalSelectedFiles - addedThisBatch.length + onWarn( + `You selected ${totalSelectedFiles} file${ + totalSelectedFiles > 1 ? 's' : '' + }. Only ${limit} ${ + limit > 1 ? 'were' : 'was' + } added. ${remainingCount} file${ + remainingCount > 1 ? 's' : '' + } ignored.`, + ) break } @@ -278,6 +296,7 @@ export default function useRootProvider({ if (!selectedFilesMap.size && !dynamicFiles) return setUploadStatus(UploadStatus.ONGOING) setUploadError('') + clearWarning() const sendEvent = !dynamicFiles const selectedFiles = dynamicFiles ? dynamicFiles @@ -363,6 +382,7 @@ export default function useRootProvider({ onError, onFileUploadProgress, onFilesUploadProgress, + clearWarning, ], ) const handleCancel = useCallback(() => { @@ -404,6 +424,8 @@ export default function useRootProvider({ setUploadStatus, uploadError, }, + warningMessage, + clearWarning, props: { mini, dark,