Reverting PWA install prompt

This protocol changed from when the old React implementation was built
and it doesn't work from a user-experience perspective now
This commit is contained in:
Jeff Avallone 2019-01-15 21:19:28 -05:00
parent 8c312a450c
commit bbdc5a3b12
7 changed files with 29 additions and 332 deletions

View File

@ -1,28 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`InstallPrompt rendering 1`] = `
<div
className="install"
>
<p
className="cta"
>
Add Regexper to your home screen?
</p>
<div
className="actions"
>
<button
className="primary"
onClick={[MockFunction]}
>
Add It
</button>
<button
onClick={[MockFunction]}
>
No Thanks
</button>
</div>
</div>
`;

View File

@ -1,21 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import style from './style.module.css';
const InstallPrompt = ({ onAccept, onReject }) => (
<div className={ style.install }>
<p className={ style.cta }>Add Regexper to your home screen?</p>
<div className={ style.actions }>
<button className={ style.primary } onClick={ onAccept }>Add It</button>
<button onClick={ onReject }>No Thanks</button>
</div>
</div>
);
InstallPrompt.propTypes = {
onAccept: PropTypes.func.isRequired,
onReject: PropTypes.func.isRequired
};
export default InstallPrompt;

View File

@ -1,38 +0,0 @@
@import url('../../globals.module.css');
.install {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: var(--color-tan);
color: var(--color-black);
}
.cta {
margin: 0;
padding: var(--spacing-margin);
text-align: center;
}
.actions {
display: flex;
flex-wrap: nowrap;
justify-content: space-evenly;
padding: var(--spacing-margin);
& button {
font-size: inherit;
line-height: 2.8rem;
border: 0 none;
background: var(--control-gradient);
color: var(--color-black);
cursor: pointer;
padding: 0;
width: 40vw;
&.primary {
font-weight: bold;
}
}
}

View File

@ -1,13 +0,0 @@
import React from 'react';
import { shallow } from 'enzyme';
import InstallPrompt from 'components/InstallPrompt';
describe('InstallPrompt', () => {
test('rendering', () => {
const component = shallow(
<InstallPrompt onReject={ jest.fn() } onAccept={ jest.fn() } />
);
expect(component).toMatchSnapshot();
});
});

View File

@ -42,94 +42,6 @@ exports[`Index Page rendering 1`] = `
</Fragment>
`;
exports[`Index Page rendering after an install prompt has been requested 1`] = `
<Fragment>
<Metadata />
<noscript>
<Message
heading="JavaScript Required"
type="error"
>
<p>
You need JavaScript to use Regexper.
</p>
<p>
If you have concerns regarding the use of tracking code on Regexper, please see the
<mockConstructor
to="/privacy"
>
Privacy Policy
</mockConstructor>
.
</p>
</Message>
</noscript>
<App
expr=""
permalinkUrl={null}
syntax="testJs"
syntaxList={
Array [
Object {
"id": "testJS",
"name": "Testing JS",
},
Object {
"id": "other",
"name": "Other",
},
]
}
/>
</Fragment>
`;
exports[`Index Page rendering after an install prompt has been requested 2`] = `
<Fragment>
<Metadata />
<noscript>
<Message
heading="JavaScript Required"
type="error"
>
<p>
You need JavaScript to use Regexper.
</p>
<p>
If you have concerns regarding the use of tracking code on Regexper, please see the
<mockConstructor
to="/privacy"
>
Privacy Policy
</mockConstructor>
.
</p>
</Message>
</noscript>
<App
expr=""
permalinkUrl={null}
syntax="testJs"
syntaxList={
Array [
Object {
"id": "testJS",
"name": "Testing JS",
},
Object {
"id": "other",
"name": "Other",
},
]
}
/>
<InstallPrompt
onAccept={[Function]}
onReject={[Function]}
/>
</Fragment>
`;
exports[`Index Page rendering with an expression on the URL 1`] = `
<Fragment>
<Metadata />

View File

@ -6,7 +6,6 @@ import URLSearchParams from '@ungap/url-search-params';
import Metadata from 'components/Metadata';
import Message from 'components/Message';
import App from 'components/App';
import InstallPrompt from 'components/InstallPrompt';
export const query = graphql`
query IndexPageQuery {
@ -40,81 +39,36 @@ const readURLHash = (location, defaultSyntax) => {
}
};
class IndexPage extends React.PureComponent {
state={
installPrompt: null
}
export const IndexPage = ({
location,
data: { site: { siteMetadata } }
}) => <>
<Metadata/>
<noscript>
<Message type="error" heading="JavaScript Required">
<p>You need JavaScript to use Regexper.</p>
<p>If you have concerns regarding the use of tracking code on Regexper,
please see the <Link to="/privacy">Privacy Policy</Link>.</p>
</Message>
</noscript>
<App
syntaxList={ siteMetadata.syntaxList }
{ ...readURLHash(location, siteMetadata.defaultSyntax) } />
</>;
static propTypes = {
location: PropTypes.object,
data: PropTypes.shape({
site: PropTypes.shape({
siteMetadata: PropTypes.shape({
defaultSyntax: PropTypes.string,
syntaxList: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string,
label: PropTypes.string
}))
})
IndexPage.propTypes = {
location: PropTypes.object,
data: PropTypes.shape({
site: PropTypes.shape({
siteMetadata: PropTypes.shape({
defaultSyntax: PropTypes.string,
syntaxList: PropTypes.arrayOf(PropTypes.shape({
id: PropTypes.string,
label: PropTypes.string
}))
})
})
}
componentDidMount() {
window.addEventListener('beforeinstallprompt', this.handleInstallPrompt);
}
componentWillUnmount() {
window.removeEventListener('beforeinstallprompt', this.handleInstallPrompt);
}
handleInstallPrompt = event => {
event.preventDefault();
this.setState({
installPrompt: event
});
}
handleInstallReject = () => {
this.setState({ installPrompt: null });
}
handleInstallAccept = () => {
const { installPrompt } = this.state;
this.setState({ installPrompt: null });
installPrompt.prompt();
}
render() {
const {
installPrompt
} = this.state;
const {
location,
data: { site: { siteMetadata } }
} = this.props;
return <>
<Metadata/>
<noscript>
<Message type="error" heading="JavaScript Required">
<p>You need JavaScript to use Regexper.</p>
<p>
If you have concerns regarding the use of tracking code on Regexper,
please see the <Link to="/privacy">Privacy Policy</Link>.
</p>
</Message>
</noscript>
<App
syntaxList={ siteMetadata.syntaxList }
{ ...readURLHash(location, siteMetadata.defaultSyntax) } />
{ installPrompt && <InstallPrompt
onAccept={ this.handleInstallAccept }
onReject={ this.handleInstallReject } /> }
</>;
}
}
})
};
export default IndexPage;

View File

@ -1,7 +1,7 @@
import React from 'react';
import { shallow } from 'enzyme';
import IndexPage from 'pages/index';
import { IndexPage } from 'pages/index';
const queryResult = {
site: {
@ -32,73 +32,4 @@ describe('Index Page', () => {
);
expect(component).toMatchSnapshot();
});
test('rendering after an install prompt has been requested', () => {
const component = shallow(
<IndexPage location={{ hash: '' }} data={ queryResult } />
);
expect(component).toMatchSnapshot();
component.instance().handleInstallPrompt({
preventDefault: jest.fn(),
prompt: jest.fn()
});
expect(component).toMatchSnapshot();
});
test('removing event listener on umount', () => {
jest.spyOn(window, 'addEventListener');
jest.spyOn(window, 'removeEventListener');
const component = shallow(
<IndexPage location={{ hash: '' }} data={ queryResult } />
);
expect(window.addEventListener).toHaveBeenCalledWith(
'beforeinstallprompt',
expect.any(Function));
component.unmount();
expect(window.removeEventListener).toHaveBeenCalledWith(
'beforeinstallprompt',
expect.any(Function));
});
test('rejecting install prompt', () => {
const component = shallow(
<IndexPage location={{ hash: '' }} data={ queryResult } />
);
const instance = component.instance();
const installEvent = {
preventDefault: jest.fn(),
prompt: jest.fn()
};
instance.handleInstallPrompt(installEvent);
instance.handleInstallReject();
expect(installEvent.prompt).not.toHaveBeenCalled();
expect(component.state('installPrompt')).toEqual(null);
});
test('accepting install prompt', () => {
const component = shallow(
<IndexPage location={{ hash: '' }} data={ queryResult } />
);
const instance = component.instance();
const installEvent = {
preventDefault: jest.fn(),
prompt: jest.fn()
};
instance.handleInstallPrompt(installEvent);
instance.handleInstallAccept();
expect(installEvent.prompt).toHaveBeenCalled();
expect(component.state('installPrompt')).toEqual(null);
});
});