(dataTransfer: DataTransfer)
| 214 | } |
| 215 | |
| 216 | export function readFromDataTransfer(dataTransfer: DataTransfer): DropItem[] { |
| 217 | let items: DropItem[] = []; |
| 218 | if (!dataTransfer) { |
| 219 | return items; |
| 220 | } |
| 221 | |
| 222 | // If our custom drag type is available, use that. This is a JSON serialized |
| 223 | // representation of all items in the drag, set when there are multiple items |
| 224 | // of the same type, or an individual item has multiple representations. |
| 225 | let hasCustomType = false; |
| 226 | if (dataTransfer.types.includes(CUSTOM_DRAG_TYPE)) { |
| 227 | try { |
| 228 | let data = dataTransfer.getData(CUSTOM_DRAG_TYPE); |
| 229 | let parsed = JSON.parse(data); |
| 230 | for (let item of parsed) { |
| 231 | items.push({ |
| 232 | kind: 'text', |
| 233 | types: new Set(Object.keys(item)), |
| 234 | getText: type => Promise.resolve(item[type]) |
| 235 | }); |
| 236 | } |
| 237 | |
| 238 | hasCustomType = true; |
| 239 | } catch { |
| 240 | // ignore |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | // Otherwise, map native drag items to items of a single representation. |
| 245 | if (!hasCustomType) { |
| 246 | let stringItems = new Map(); |
| 247 | for (let item of dataTransfer.items) { |
| 248 | if (item.kind === 'string') { |
| 249 | // The data for all formats must be read here because the data transfer gets |
| 250 | // cleared out after the event handler finishes. If the item has an empty string |
| 251 | // as a type, the mime type is unknown. Map to a generic mime type instead. |
| 252 | stringItems.set(item.type || GENERIC_TYPE, dataTransfer.getData(item.type)); |
| 253 | } else if (item.kind === 'file') { |
| 254 | // Despite the name, webkitGetAsEntry is also implemented in Firefox and Edge. |
| 255 | // In the future, we may use getAsFileSystemHandle instead, but that's currently |
| 256 | // only implemented in Chrome. |
| 257 | if (typeof item.webkitGetAsEntry === 'function') { |
| 258 | let entry: FileSystemEntry | null = item.webkitGetAsEntry(); |
| 259 | // eslint-disable-next-line max-depth |
| 260 | if (!entry) { |
| 261 | // For some reason, Firefox includes an item with type image/png when copy |
| 262 | // and pasting any file or directory (no matter the type), but returns `null` for both |
| 263 | // item.getAsFile() and item.webkitGetAsEntry(). Safari works as expected. Ignore this |
| 264 | // item if this happens. See https://bugzilla.mozilla.org/show_bug.cgi?id=1699743. |
| 265 | // This was recently fixed in Chrome Canary: https://bugs.chromium.org/p/chromium/issues/detail?id=1175483. |
| 266 | continue; |
| 267 | } |
| 268 | |
| 269 | // eslint-disable-next-line max-depth |
| 270 | if (entry.isFile) { |
| 271 | items.push(createFileItem(item.getAsFile())); |
| 272 | } else if (entry.isDirectory) { |
| 273 | items.push(createDirectoryItem(entry)); |
no test coverage detected