(dataTransfer: DataTransfer, items: DragItem[])
| 95 | } |
| 96 | |
| 97 | export function writeToDataTransfer(dataTransfer: DataTransfer, items: DragItem[]): void { |
| 98 | // The data transfer API doesn't support more than one item of a given type at once. |
| 99 | // In addition, only a small set of types are supported natively for transfer between applications. |
| 100 | // We allow for both multiple items, as well as multiple representations of a single item. |
| 101 | // In order to make our API work with the native API, we serialize all items to JSON and |
| 102 | // store as a single native item. We only need to do this if there is more than one item |
| 103 | // of the same type, or if an item has more than one representation. Otherwise the native |
| 104 | // API is sufficient. |
| 105 | // |
| 106 | // The DataTransferItemList API also theoretically supports adding files, which would enable |
| 107 | // dragging binary data out of the browser onto the user's desktop for example. Unfortunately, |
| 108 | // this does not currently work in any browser, so it is not currently supported by our API. |
| 109 | // See e.g. https://bugs.chromium.org/p/chromium/issues/detail?id=438479. |
| 110 | let groupedByType = new Map<string, string[]>(); |
| 111 | let needsCustomData = false; |
| 112 | let customData: Array<{}> = []; |
| 113 | for (let item of items) { |
| 114 | let types = Object.keys(item); |
| 115 | if (types.length > 1) { |
| 116 | needsCustomData = true; |
| 117 | } |
| 118 | |
| 119 | let dataByType = {}; |
| 120 | for (let type of types) { |
| 121 | let typeItems = groupedByType.get(type); |
| 122 | if (!typeItems) { |
| 123 | typeItems = []; |
| 124 | groupedByType.set(type, typeItems); |
| 125 | } else { |
| 126 | needsCustomData = true; |
| 127 | } |
| 128 | |
| 129 | let data = item[type]; |
| 130 | dataByType[type] = data; |
| 131 | typeItems.push(data); |
| 132 | } |
| 133 | |
| 134 | customData.push(dataByType); |
| 135 | } |
| 136 | |
| 137 | for (let [type, items] of groupedByType) { |
| 138 | if (NATIVE_DRAG_TYPES.has(type)) { |
| 139 | // Only one item of a given type can be set on a data transfer. |
| 140 | // Join all of the items together separated by newlines. |
| 141 | let data = items.join('\n'); |
| 142 | dataTransfer.items.add(data, type); |
| 143 | } else { |
| 144 | // Set data to the first item so we have access to the list of types. |
| 145 | dataTransfer.items.add(items[0], type); |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | if (needsCustomData) { |
| 150 | let data = JSON.stringify(customData); |
| 151 | dataTransfer.items.add(data, CUSTOM_DRAG_TYPE); |
| 152 | } |
| 153 | } |
| 154 |
no test coverage detected