Adds install button to Squoosh

This commit is contained in:
Pete LePage
2020-06-23 16:10:40 -04:00
parent 3a5c0aa30c
commit 265e6db2bd
3 changed files with 135 additions and 1 deletions

View File

@@ -47,11 +47,27 @@ interface Props {
} }
interface State { interface State {
fetchingDemoIndex?: number; fetchingDemoIndex?: number;
deferredPrompt?: BeforeInstallPromptEvent;
installSource?: String;
} }
export default class Intro extends Component<Props, State> { export default class Intro extends Component<Props, State> {
state: State = {}; state: State = {
deferredPrompt: undefined,
installSource: undefined,
};
private fileInput?: HTMLInputElement; private fileInput?: HTMLInputElement;
private installButton?: HTMLButtonElement;
constructor() {
super();
// Listen for beforeinstallprompt events, indicating Squoosh is installable.
window.addEventListener('beforeinstallprompt', this.onBeforeInstallPromptEvent);
// Listen for the appinstalled event, indicating Squoosh has been installed.
window.addEventListener('appinstalled', this.onAppInstalled);
}
@bind @bind
private resetFileInput() { private resetFileInput() {
@@ -90,6 +106,62 @@ export default class Intro extends Component<Props, State> {
} }
} }
@bind
private onBeforeInstallPromptEvent(event: BeforeInstallPromptEvent) {
// Don't show the mini-infobar on mobile
event.preventDefault();
// Save the beforeinstallprompt event so it can be called later.
this.setState({ deferredPrompt: event });
// Log the event.
ga('send', 'event', 'pwa-install', 'available');
// Make the install button visible
this.installButton!.style.display = 'inline-block';
}
@bind
private async onInstallClick(event: Event) {
// Get the deferred beforeinstallprompt event
const deferredPrompt = this.state.deferredPrompt;
// If there's no deferred prompt, bail.
if (!deferredPrompt) return;
// Set the install source as the intro install button.
const installSource = 'introInstallButton';
this.setState({ installSource });
// Show the browser install prompt
deferredPrompt.prompt();
// Wait for the user to accept or dismiss the install prompt
const response = await deferredPrompt.userChoice;
// Get the outcome and log it
const outcome = response.outcome;
ga('send', 'event', 'pwa-install', installSource, outcome);
// If the prompt was dismissed, clear the installSource.
if (outcome === 'dismissed') {
this.setState({ installSource: undefined });
}
}
@bind
private onAppInstalled() {
// If install button is visible, hide it.
const installButton = this.installButton;
if (installButton) {
installButton.style.display = 'none';
}
// Try to get the install, if it's not set, use 'browser'
const source = this.state.installSource || 'browser';
ga('send', 'event', 'pwa-install', 'installed', source);
}
render({ }: Props, { fetchingDemoIndex }: State) { render({ }: Props, { fetchingDemoIndex }: State) {
return ( return (
<div class={style.intro}> <div class={style.intro}>
@@ -132,6 +204,16 @@ export default class Intro extends Component<Props, State> {
)} )}
</ul> </ul>
</div> </div>
<div>
<button
ref={linkRef(this, 'installButton')}
type="button"
class={style.installButton}
onClick={this.onInstallClick}
>
Install Squoosh
</button>
</div>
<ul class={style.relatedLinks}> <ul class={style.relatedLinks}>
<li><a href="https://github.com/GoogleChromeLabs/squoosh/">View the code</a></li> <li><a href="https://github.com/GoogleChromeLabs/squoosh/">View the code</a></li>
<li><a href="https://github.com/GoogleChromeLabs/squoosh/issues">Report a bug</a></li> <li><a href="https://github.com/GoogleChromeLabs/squoosh/issues">Report a bug</a></li>

32
src/components/intro/missing-types.d.ts vendored Normal file
View File

@@ -0,0 +1,32 @@
/**
* The BeforeInstallPromptEvent is fired at the Window.onbeforeinstallprompt handler
* before a user is prompted to "install" a web site to a home screen on mobile.
*/
interface BeforeInstallPromptEvent extends Event {
/**
* Returns an array of DOMString items containing the platforms on which the event was dispatched.
* This is provided for user agents that want to present a choice of versions to the user such as,
* for example, "web" or "play" which would allow the user to chose between a web version or
* an Android version.
*/
readonly platforms: Array<string>;
/**
* Returns a Promise that resolves to a DOMString containing either "accepted" or "dismissed".
*/
readonly userChoice: Promise<{
outcome: 'accepted' | 'dismissed',
platform: string
}>;
/**
* Allows a developer to show the install prompt at a time of their own choosing.
* This method returns a Promise.
*/
prompt(): Promise<void>;
}
interface WindowEventMap {
"beforeinstallprompt": BeforeInstallPromptEvent;
}

View File

@@ -170,6 +170,26 @@
--color: #fff; --color: #fff;
} }
.install-button {
composes: unbutton from '../../lib/util.scss';
&:hover,
&:focus {
background: #f5f5f5;
}
background: #fff;
border: 1px solid #e8e8e8;
margin-top: 1em;
align-items: center;
padding: 14px;
font-size: 1.3rem;
display: none;
}
.related-links { .related-links {
display: flex; display: flex;
padding: 0; padding: 0;