Skip to content

Commit f9c6343

Browse files
authored
fix: not possible to drag&drop file with multiple dots (#487)
* remove unused function * treat file extensions and types as they are received on the property and ensure that for file extensions, only the last entry after splitting "." is used
1 parent 8bc217c commit f9c6343

File tree

1 file changed

+52
-36
lines changed

1 file changed

+52
-36
lines changed

packages/uui-file-dropzone/lib/uui-file-dropzone.element.ts

Lines changed: 52 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,45 @@ export class UUIFileDropzoneElement extends LabelMixin('', LitElement) {
6161
@query('#dropzone')
6262
private _dropzone!: HTMLElement;
6363

64+
private _acceptedFileExtensions: string[] = [];
65+
private _acceptedMimeTypes: string[] = [];
66+
6467
/**
65-
* Comma-separated list of accepted filetypes. Will allow all types if empty.
68+
* Comma-separated list of accepted mime types or file extensions (denoted with a `.`).
69+
* If this is left empty, it will allow all types.
70+
*
6671
* @type {string}
6772
* @attr
68-
* @default false
6973
* @examples [
70-
* "image/png,image/jpeg,image/gif",
71-
* "gif,png,jpg,jpeg",
74+
* "image/*,application/pdf",
75+
* ".gif,.png,.jpg,.jpeg,.pdf",
7276
* ]
7377
*/
7478
@property({ type: String })
75-
public accept: string = '';
79+
public set accept(value: string) {
80+
if (value) {
81+
const mimetypes: string[] = [];
82+
const fileextensions: string[] = [];
83+
84+
// Create the arrays defined above
85+
value.split(',').forEach(item => {
86+
item = item.trim().toLowerCase();
87+
88+
// If the item is a mime type, add it to the accept list
89+
if (/[a-z]+\/[a-z*]/s.test(item)) {
90+
mimetypes.push(item);
91+
} else {
92+
fileextensions.push(item.replace(/^\./, ''));
93+
}
94+
});
95+
96+
this._acceptedMimeTypes = mimetypes;
97+
this._acceptedFileExtensions = fileextensions;
98+
} else {
99+
this._acceptedMimeTypes = [];
100+
this._acceptedFileExtensions = [];
101+
}
102+
}
76103

77104
/**
78105
* Allows for multiple files to be selected.
@@ -105,40 +132,20 @@ export class UUIFileDropzoneElement extends LabelMixin('', LitElement) {
105132
demandCustomElement(this, 'uui-symbol-file-dropzone');
106133
}
107134

108-
protected _checkIsItDirectory(dtItem: DataTransferItem): boolean {
109-
// @ts-ignore // TODO: fix typescript error
110-
return !dtItem.type ? dtItem.webkitGetAsEntry().isDirectory : false;
111-
}
112-
113135
private async _getAllFileEntries(
114136
dataTransferItemList: DataTransferItemList
115137
): Promise<File[]> {
116138
const fileEntries: File[] = [];
117139
// Use BFS to traverse entire directory/file structure
118140
const queue = [...dataTransferItemList];
119141

120-
const acceptList: string[] = [];
121-
const wildcards: string[] = [];
122-
123-
// if the accept filer is set
124-
if (this.accept) {
125-
// Create the arrays defined above
126-
this.accept.split(',').forEach(item => {
127-
if (item.includes('*')) {
128-
wildcards.push(item.split('*')[0].trim().toLowerCase());
129-
} else {
130-
acceptList.push(item.trim().toLowerCase());
131-
}
132-
});
133-
}
134-
135142
while (queue.length > 0) {
136143
const entry = queue.shift()!;
137144

138145
if (entry.kind === 'file') {
139146
const file = entry.getAsFile();
140147
if (!file) continue;
141-
if (this._isAccepted(acceptList, wildcards, file)) {
148+
if (this._isAccepted(file)) {
142149
fileEntries.push(file);
143150
}
144151
} else if (entry.kind === 'directory') {
@@ -179,24 +186,33 @@ export class UUIFileDropzoneElement extends LabelMixin('', LitElement) {
179186
}
180187
}
181188

182-
private _isAccepted(acceptList: string[], wildcards: string[], file: File) {
183-
if (acceptList.length === 0 && wildcards.length === 0) {
189+
private _isAccepted(file: File) {
190+
if (
191+
this._acceptedFileExtensions.length === 0 &&
192+
this._acceptedMimeTypes.length === 0
193+
) {
184194
return true;
185195
}
186196

187197
const fileType = file.type.toLowerCase();
188-
const fileExtension = '.' + file.name.split('.')[1].toLowerCase();
189-
190-
if (acceptList.includes(fileExtension)) {
191-
return true;
192-
}
198+
const fileExtension = file.name.split('.').pop();
193199

194-
if (acceptList.includes(fileType)) {
200+
if (
201+
fileExtension &&
202+
this._acceptedFileExtensions.includes(fileExtension.toLowerCase())
203+
) {
195204
return true;
196205
}
197206

198-
if (wildcards.some(wildcard => fileType.startsWith(wildcard))) {
199-
return true;
207+
for (const mimeType in this._acceptedMimeTypes) {
208+
if (fileType === mimeType) {
209+
return true;
210+
} else if (
211+
mimeType.endsWith('/*') &&
212+
fileType.startsWith(mimeType.replace('/*', ''))
213+
) {
214+
return true;
215+
}
200216
}
201217

202218
return false;

0 commit comments

Comments
 (0)