Skip to content

Commit

Permalink
fix(storage): fixing drop handler for file extensions (#4649)
Browse files Browse the repository at this point in the history
  • Loading branch information
dbanksdesign authored Nov 7, 2023
1 parent bb4e683 commit 1dbe3f4
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 43 deletions.
8 changes: 8 additions & 0 deletions .changeset/dull-cheetahs-deliver.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@aws-amplify/ui-react-storage": patch
"@aws-amplify/ui-react": patch
---

fix(storage): fixing drop handler for file extensions

Previously, adding a file extension for an `acceptedFileTypes` when a customer would drop a file it would show as rejected even if it was a valid file type. This fixes that issue.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import awsExports from '@environments/storage/file-uploader/src/aws-exports';
export default awsExports;
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Amplify } from 'aws-amplify';
import { StorageManager } from '@aws-amplify/ui-react-storage';
import '@aws-amplify/ui-react/styles.css';
import awsExports from './aws-exports';
Amplify.configure(awsExports);

export function StorageManagerExample() {
return (
<>
<StorageManager
acceptedFileTypes={['.png']}
accessLevel="public"
maxFileCount={1}
showThumbnails
/>
</>
);
}
export default StorageManagerExample;
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { filterAllowedFiles } from '../filterAllowedFiles';

describe('filterAllowFiles', () => {
const droppedFiles = [
new File([], 'test.jpg', { type: 'image/jpg' }),
new File([], 'test.png', { type: 'image/png' }),
];

it('should work with * MIME types', () => {
const { acceptedFiles, rejectedFiles } = filterAllowedFiles(droppedFiles, [
'image/*',
]);
expect(rejectedFiles).toHaveLength(0);
expect(acceptedFiles).toHaveLength(2);
});

it('should work with extension types', () => {
const { acceptedFiles, rejectedFiles } = filterAllowedFiles(droppedFiles, [
'.png',
]);
expect(rejectedFiles).toHaveLength(1);
expect(acceptedFiles).toHaveLength(1);
});

it('should work with *', () => {
const { acceptedFiles, rejectedFiles } = filterAllowedFiles(droppedFiles, [
'*',
]);
expect(rejectedFiles).toHaveLength(0);
expect(acceptedFiles).toHaveLength(2);
});
});
50 changes: 50 additions & 0 deletions packages/react/src/primitives/DropZone/filterAllowedFiles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Drag event file shape is different than the drop event fileshape
type DragFile =
| {
kind: string;
type: string;
name?: string;
}
| File;

export function filterAllowedFiles<FileType extends DragFile = DragFile>(
files: FileType[],
acceptedFileTypes: string[]
): { acceptedFiles: FileType[]; rejectedFiles: FileType[] } {
// Allow any files if acceptedFileTypes is undefined, empty array, or contains '*'
if (
!acceptedFileTypes ||
acceptedFileTypes.length === 0 ||
acceptedFileTypes.includes('*')
) {
return { acceptedFiles: files, rejectedFiles: [] };
}
const acceptedFiles: FileType[] = [];
const rejectedFiles: FileType[] = [];

function filterFile(file: DragFile) {
const { type = '', name = '' } = file;
const mimeType = type.toLowerCase();
const baseMimeType = mimeType.split('/')[0];

return acceptedFileTypes.some((type) => {
const validType = type.trim().toLowerCase();
// if the accepted file type is a file extension
// it will start with '.', check against the file name
if (validType.charAt(0) === '.') {
return name.toLowerCase().endsWith(validType);
}
// This is something like a image/* mime type
if (validType.endsWith('/*')) {
return baseMimeType === validType.split('/')[0];
}
return mimeType === validType;
});
}

files.forEach((file) => {
(filterFile(file) ? acceptedFiles : rejectedFiles).push(file);
});

return { acceptedFiles, rejectedFiles };
}
44 changes: 1 addition & 43 deletions packages/react/src/primitives/DropZone/useDropZone.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,7 @@
import { useState } from 'react';
import { UseDropZoneProps, UseDropZoneReturn, DragState } from './types';
import { isFunction } from '@aws-amplify/ui';

type DragFile =
| {
kind: string;
type: string;
}
| File;

function filterAllowedFiles<FileType extends DragFile = DragFile>(
files: FileType[],
acceptedFileTypes: string[]
): { acceptedFiles: FileType[]; rejectedFiles: FileType[] } {
// Allow any files if acceptedFileTypes is undefined, empty array, or contains '*'
if (
!acceptedFileTypes ||
acceptedFileTypes.length === 0 ||
acceptedFileTypes.includes('*')
) {
return { acceptedFiles: files, rejectedFiles: [] };
}
const acceptedFiles: FileType[] = [];
const rejectedFiles: FileType[] = [];

function filterFile({ type = '' }) {
const mimeType = type.toLowerCase();
const baseMimeType = mimeType.split('/')[0];

return acceptedFileTypes.some((type) => {
const validType = type.trim().toLowerCase();
if (validType.endsWith('/*')) {
// This is something like a image/* mime type
return baseMimeType === validType.split('/')[0];
}
return mimeType === validType;
});
}

files.forEach((file) => {
(filterFile(file) ? acceptedFiles : rejectedFiles).push(file);
});

return { acceptedFiles, rejectedFiles };
}
import { filterAllowedFiles } from './filterAllowedFiles';

export function useDropZone({
onDropComplete,
Expand Down

0 comments on commit 1dbe3f4

Please sign in to comment.