| function delayByFrames(f, num_frames) { |
| function recurse(depth) { |
| if (depth == 0) |
| f(); |
| else |
| requestAnimationFrame(() => recurse(depth-1)); |
| } |
| recurse(num_frames); |
| } |
| |
| // Returns a Promise which is resolved with the event object when the event is |
| // fired. |
| function getEvent(eventType) { |
| return new Promise(resolve => { |
| document.body.addEventListener(eventType, e => resolve(e), {once: true}); |
| }); |
| } |
| |
| |
| // Returns a Promise which is resolved with a "true" iff transient activation |
| // was available and successfully consumed. |
| // |
| // This function relies on Fullscreen API to check/consume user activation |
| // state. |
| async function consumeTransientActivation() { |
| try { |
| await document.body.requestFullscreen(); |
| await document.exitFullscreen(); |
| return true; |
| } catch(e) { |
| return false; |
| } |
| } |
| |
| function receiveMessage(type) { |
| return new Promise((resolve) => { |
| window.addEventListener("message", function listener(event) { |
| if (typeof event.data !== "string") { |
| return; |
| } |
| const data = JSON.parse(event.data); |
| if (data.type === type) { |
| window.removeEventListener("message", listener); |
| resolve(data); |
| } |
| }); |
| }); |
| } |