|
|
|
@ -126,6 +126,38 @@ polyfill();
|
|
|
|
|
|
|
|
|
|
window.EXCALIDRAW_THROTTLE_RENDER = true;
|
|
|
|
|
|
|
|
|
|
declare global {
|
|
|
|
|
interface BeforeInstallPromptEventChoiceResult {
|
|
|
|
|
outcome: "accepted" | "dismissed";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface BeforeInstallPromptEvent extends Event {
|
|
|
|
|
prompt(): Promise<void>;
|
|
|
|
|
userChoice: Promise<BeforeInstallPromptEventChoiceResult>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface WindowEventMap {
|
|
|
|
|
beforeinstallprompt: BeforeInstallPromptEvent;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let pwaEvent: BeforeInstallPromptEvent | null = null;
|
|
|
|
|
|
|
|
|
|
// Adding a listener outside of the component as it may (?) need to be
|
|
|
|
|
// subscribed early to catch the event.
|
|
|
|
|
//
|
|
|
|
|
// Also note that it will fire only if certain heuristics are met (user has
|
|
|
|
|
// used the app for some time, etc.)
|
|
|
|
|
window.addEventListener(
|
|
|
|
|
"beforeinstallprompt",
|
|
|
|
|
(event: BeforeInstallPromptEvent) => {
|
|
|
|
|
// prevent Chrome <= 67 from automatically showing the prompt
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
// cache for later use
|
|
|
|
|
pwaEvent = event;
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let isSelfEmbedding = false;
|
|
|
|
|
|
|
|
|
|
if (window.self !== window.top) {
|
|
|
|
@ -1100,6 +1132,21 @@ const ExcalidrawWrapper = () => {
|
|
|
|
|
);
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
label: t("labels.installPWA"),
|
|
|
|
|
category: DEFAULT_CATEGORIES.app,
|
|
|
|
|
predicate: () => !!pwaEvent,
|
|
|
|
|
perform: () => {
|
|
|
|
|
if (pwaEvent) {
|
|
|
|
|
pwaEvent.prompt();
|
|
|
|
|
pwaEvent.userChoice.then(() => {
|
|
|
|
|
// event cannot be reused, but we'll hopefully
|
|
|
|
|
// grab new one as the event should be fired again
|
|
|
|
|
pwaEvent = null;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
]}
|
|
|
|
|
/>
|
|
|
|
|
</Excalidraw>
|
|
|
|
|