| 263 | } |
| 264 | |
| 265 | void EmscriptenFilePicker::FetchDirectoryAsync(Containers::Function<void(Containers::ArrayView<EmscriptenFileStream>)>&& callback) |
| 266 | { |
| 267 | if (_activeCallback) { |
| 268 | // Another callback is already active, cancel this one |
| 269 | callback({}); |
| 270 | return; |
| 271 | } |
| 272 | |
| 273 | auto window = emscripten::val::global("window"); |
| 274 | if (emscripten::val("showDirectoryPicker").in(window)) { |
| 275 | _supportsCancel = true; |
| 276 | |
| 277 | auto dirHandle = window.call<emscripten::val>("showDirectoryPicker").await(); |
| 278 | auto values = dirHandle.call<emscripten::val>("values"); // Async iterator |
| 279 | auto prevSize = _files.size(); |
| 280 | while (true) { |
| 281 | auto entry = values.call<emscripten::val>("next").await(); |
| 282 | if (entry["done"].as<bool>()) { |
| 283 | break; // End of async iteration |
| 284 | } |
| 285 | |
| 286 | auto entryValue = entry["value"]; |
| 287 | if (entryValue["kind"].as<std::string>() == "file") { |
| 288 | _files.emplace_back(entryValue.call<emscripten::val>("getFile").await()); |
| 289 | } |
| 290 | } |
| 291 | |
| 292 | // Exclude previously added files |
| 293 | callback(arrayView(_files).exceptPrefix(prevSize)); |
| 294 | return; |
| 295 | } |
| 296 | |
| 297 | _activeCallback = Death::move(callback); |
| 298 | |
| 299 | // Create file input element which will display a native file dialog |
| 300 | auto document = emscripten::val::global("document"); |
| 301 | auto input = document.call<emscripten::val>("createElement", emscripten::val("input")); |
| 302 | input.set("type", "file"); |
| 303 | input.set("style", "display:none"); |
| 304 | input.set("multiple", "multiple"); |
| 305 | input.set("webkitdirectory", "webkitdirectory"); |
| 306 | |
| 307 | // http://perfectionkills.com/detecting-event-support-without-browser-sniffing |
| 308 | _supportsCancel = false; |
| 309 | if (emscripten::val("oncancel").in(input)) { |
| 310 | _supportsCancel = true; |
| 311 | } else { |
| 312 | input.set("oncancel", emscripten::val("return;")); |
| 313 | if (input["oncancel"].typeOf().as<std::string>() == "function") { |
| 314 | _supportsCancel = true; |
| 315 | } |
| 316 | } |
| 317 | |
| 318 | input.set("onchange", emscripten::val::module_property("jsReadFiles")); |
| 319 | input.set("oncancel", emscripten::val::module_property("jsCancelReadFiles")); |
| 320 | input.set("data-callbackContext", emscripten::val(std::size_t(this))); |
| 321 | |
| 322 | auto body = document["body"]; |
nothing calls this directly
no test coverage detected