react-pwa-add-to-homescreen
Version:
React Component install PWA - Add To Homescreen
296 lines (275 loc) • 15.5 kB
JavaScript
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
import { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function styleInject(css, ref) {
if ( ref === void 0 ) ref = {};
var insertAt = ref.insertAt;
if (!css || typeof document === 'undefined') { return; }
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (insertAt === 'top') {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
var css_248z = ".add-to-home-screen-pwa {\n display: table;\n position: fixed;\n text-align: center;\n z-index: 1000;\n left: 50%;\n transform: translate(-50%, 0);\n padding: 10px;\n width: 100%;\n bottom: 0;\n box-shadow: 0 -4px 4px rgb(0 0 0 / 4%);\n border: 1px solid #cecece;\n cursor: pointer;\n color: #000;\n background: url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='50.0' height='50.0' viewBox='0 0 40.0 100.0'><path opacity='.6' fill='black' d='M35.6 34.4L28 26.8l7.6-7.6c.2-.2.2-.5 0-.7l-.5-.5c-.2-.2-.5-.2-.7 0l-7.6 7.6-7.5-7.6c-.2-.2-.5-.2-.7 0l-.6.6c-.2.2-.2.5 0 .7l7.6 7.6-7.6 7.5c-.2.2-.2.5 0 .7l.5.5c.2.2.5.2.7 0l7.6-7.6 7.6 7.6c.2.2.5.2.7 0l.5-.5c.2-.2.2-.5 0-.7z'/></svg>\") no-repeat right top #fff;\n}\n\n.add-to-home-screen-pwa__notify {\n display: table-cell;\n}\n\n.add-to-home-screen-pwa__notify p {\n font-size: inherit;\n text-rendering: optimizeLegibility;\n}\n\n.add-to-home-screen-pwa__notify p:first-of-type {\n margin-top: .7rem;\n}\n\n.add-to-home-screen-pwa__notify p.heading {\n font-weight: 600;\n}\n\n.add-to-home-screen-pwa__notify .home, .share {\n background-repeat: no-repeat;\n background-size: cover;\n width: 1.25em;\n height: 1.25em;\n display: inline-block;\n vertical-align: text-bottom;\n}\n\n.add-to-home-screen-pwa__notify .home {\n background-image: url(\"data:image/svg+xml,<svg height='300' width='300' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><switch><g><path d='M81 2.5H19C9.9 2.5 2.5 9.9 2.5 19v62c0 9.1 7.4 16.5 16.5 16.5h62c9.1 0 16.5-7.4 16.5-16.5V19c0-9.1-7.4-16.5-16.5-16.5zm-3.2 51.7H54.2v23.6c0 2.3-1.9 4.2-4.2 4.2-1.2 0-2.2-.5-3-1.2-.8-.8-1.2-1.8-1.2-3V54.2H22.2c-1.2 0-2.2-.5-3-1.2-.8-.8-1.2-1.8-1.2-3 0-2.3 1.9-4.2 4.2-4.2h23.6V22.2c0-2.3 1.9-4.2 4.2-4.2 2.3 0 4.2 1.9 4.2 4.2v23.6h23.6c2.3 0 4.2 1.9 4.2 4.2.1 2.3-1.8 4.2-4.2 4.2z'/></g></switch></svg>\");\n}\n\n.add-to-home-screen-pwa__notify .share {\n background-image: url(\"data:image/svg+xml,<svg height='300' width='300' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><path d='M79.636 28.404H59.515a2.5 2.5 0 1 0 0 5H77.636v55.271H22.364V33.404h18.509a2.5 2.5 0 0 0 0-5H20.364c-1.65 0-3 1.35-3 3v59.271c0 1.65 1.35 3 3 3h59.271c1.65 0 3-1.35 3-3V31.404c.001-1.65-1.349-3-2.999-3z'/><path d='M34.761 23.297l12.801-9.126v46.96a2.439 2.439 0 0 0 4.878 0V14.17l12.802 9.126a2.736 2.736 0 0 0 3.822-.641 2.74 2.74 0 0 0-.641-3.823l-16.832-12a2.74 2.74 0 0 0-3.182 0l-16.832 12a2.741 2.741 0 1 0 3.184 4.465z'/></svg>\");\n}\n\n.add-to-home-screen-pwa__notify button {\n display: inline-block;\n background-color: #c86b60;\n color: #fff;\n text-transform: uppercase;\n border: 1px solid transparent;\n border-radius: 8px;\n font-family: inherit;\n font-size: 1rem;\n font-weight: 600;\n text-align: center;\n cursor: pointer;\n letter-spacing: 0.1em;\n padding: 1.1em 3.134em;\n}\n";
styleInject(css_248z);
var TRANSLATE_SAFARI_TAP_SHARE = 'Tap "Share"';
var TRANSLATE_SAFARI_ADD_HOME_SCREEN = 'select "Add to Home Screen"';
var TRANSLATE_CHROME_ADD_HOME_SCREEN = 'Click "Add to Home Screen" in your browser menu';
var TRANSLATE_CHROME_INSTALL = 'The app icon will be displayed on your screen';
var TRANSLATE_INSTALL_BUTTON = 'install';
var COOKIE_NAME = 'add-to-home-screen-pwa';
var COOKIE_EXPIRE_DAYS = 30;
function Chrome(_a) {
var translate = _a.translate, styles = _a.styles;
return jsxs(Fragment, { children: [translate.headline ?
jsx("p", __assign({ className: 'heading', style: styles.heading }, { children: translate.headline })) : null, jsxs("p", { children: [translate.chromiumAddHomeScreen || TRANSLATE_CHROME_ADD_HOME_SCREEN, translate.bottomline ? jsxs(Fragment, { children: [jsx("br", {}), translate.bottomline] }) : null] })] });
}
function Safari$1(_a) {
var translate = _a.translate, styles = _a.styles;
return (jsxs(Fragment, { children: [translate.headline ?
jsx("p", __assign({ className: 'heading', style: styles.heading }, { children: translate.headline })) : null, jsxs("p", { children: [translate.safariTapShare || TRANSLATE_SAFARI_TAP_SHARE, " ", jsx("i", { className: 'share' }), jsx("br", {}), translate.safariAddHomeScreen || TRANSLATE_SAFARI_ADD_HOME_SCREEN, " ", jsx("i", { className: 'home' }), translate.bottomline ? jsxs(Fragment, { children: [jsx("br", {}), translate.bottomline] }) : null] })] }));
}
function Safari(_a) {
var translate = _a.translate, onClick = _a.onClick, styles = _a.styles;
return jsxs(Fragment, { children: [translate.headline ?
jsx("p", __assign({ className: 'heading', style: styles.heading }, { children: translate.headline })) : null, jsx("p", { children: translate.chromiumInstall || TRANSLATE_CHROME_INSTALL }), jsx("button", __assign({ onClick: onClick, style: styles.button }, { children: translate.buttonInstall || TRANSLATE_INSTALL_BUTTON }))] });
}
var MemoSession = /** @class */ (function () {
function MemoSession() {
this._session = { firstVisit: false };
}
Object.defineProperty(MemoSession.prototype, "firstVisit", {
get: function () {
return this._session.firstVisit;
},
enumerable: false,
configurable: true
});
Object.defineProperty(MemoSession.prototype, "eventInstall", {
get: function () {
return this._session.eventInstall;
},
enumerable: false,
configurable: true
});
MemoSession.prototype.setSession = function (data) {
this._session = __assign(__assign({}, this._session), data);
};
return MemoSession;
}());
var testPlatform = {
iPhone: /iphone/i,
android: /android/i,
chrome: /Chrome/i,
version: /Version/i,
safari: /Safari/i,
};
function getPlatform() {
var navigator = window.navigator;
var userAgent = navigator.userAgent;
var isPwaIOS = !!(navigator === null || navigator === void 0 ? void 0 : navigator.standalone);
var isPwaChrome = window.matchMedia('(display-mode: standalone)').matches;
var isChromium = 'onbeforeinstallprompt' in window;
var isAndroid = testPlatform.android.test(userAgent);
var isChrome = testPlatform.chrome.test(userAgent);
var isExistVersion = testPlatform.version.test(userAgent);
var isSafari = testPlatform.safari.test(userAgent) && isExistVersion;
var isIPhone = testPlatform.iPhone.test(userAgent);
if (isPwaIOS || isPwaChrome) {
return 'standalone';
}
else if (isIPhone && isSafari) {
return 'safari-iphone';
}
else if (isChrome && isChromium && isAndroid) {
return 'chrome-android';
}
else if (isChromium && isAndroid) {
return 'chromium-android';
}
return null;
}
function setCookie(name, days, val) {
if (val === void 0) { val = 'notified'; }
var currentDate = new Date();
var expires = new Date(currentDate.setDate(currentDate.getDate() + days));
document.cookie = "".concat(name, "=").concat(val, "; expires=").concat(expires.toUTCString(), ";");
}
function getCookieValue(name) {
var b = document.cookie.match('(^|;)\\s*' + name + '\\s*=\\s*([^;]+)');
return b ? b.pop() : '';
}
var memoSession = new MemoSession();
function AddToHomeScreen(_a) {
var props = __rest(_a, []);
var _b = useState(null), component = _b[0], setComponent = _b[1];
var _c = useState(memoSession.eventInstall), eventInstall = _c[0], setEventInstall = _c[1];
var _d = useState(), initData = _d[0], setInitData = _d[1];
var cookieName = (props.cookie.name || COOKIE_NAME);
var expireDays = (props.cookie.expireDays || COOKIE_EXPIRE_DAYS);
function handleBeforeInstallPrompt(event) {
event.preventDefault();
if (!memoSession.eventInstall) {
setEventInstall(event);
memoSession.setSession({ eventInstall: event });
}
}
function handleAppInstalled() {
// onCloseNotify(expireDays + 30);
}
function init() {
var cookieVal = getCookieValue(cookieName);
if (props.skipFirstVisit && !cookieVal) {
setCookie(cookieName, 90, 'initialized');
memoSession.setSession({ firstVisit: true });
return;
}
if (memoSession.firstVisit) {
return;
}
var existInstall = 'onbeforeinstallprompt' in window;
var existOnInstalled = 'onappinstalled' in window;
var timeoutInit = existInstall ? Math.max(1500, props.delayNotify) : props.delayNotify;
if (existInstall) {
window.addEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
}
if (existOnInstalled) {
window.addEventListener('appinstalled', handleAppInstalled);
}
var platform = getPlatform();
var delayTimeout = setTimeout(function () {
var isSupported = !!(platform);
var isNotNotify = cookieVal !== 'notified';
setInitData({ platform: platform, openNotify: isSupported && isNotNotify && platform !== 'standalone' });
}, timeoutInit);
return function () {
if (existInstall) {
window.removeEventListener('beforeinstallprompt', handleBeforeInstallPrompt);
}
if (existOnInstalled) {
window.removeEventListener('appinstalled', handleAppInstalled);
}
clearTimeout(delayTimeout);
};
}
function onCloseNotify(cookieExpDays) {
if (cookieExpDays === void 0) { cookieExpDays = 0; }
setCookie(cookieName, cookieExpDays || expireDays);
if (initData) {
setInitData(__assign(__assign({}, initData), { openNotify: false }));
}
}
function onInstallApp(event) {
event.stopPropagation();
if (eventInstall) {
eventInstall.prompt()
.then(function () { return eventInstall.userChoice; })
.then(function (choiceResult) {
onCloseNotify(choiceResult.outcome === 'accepted' ? expireDays + 30 : expireDays);
setEventInstall(undefined);
memoSession.setSession({ eventInstall: undefined });
})
.catch(function () { return onCloseNotify(); });
}
else {
onCloseNotify();
}
}
function renderComponent() {
if (!initData || !initData.openNotify) {
return setComponent(function () { return null; });
}
setComponent(RenderHOC);
}
function RenderHOC() {
return (jsx("div", __assign({ className: 'add-to-home-screen-pwa', style: props.styles.body }, { children: eventInstall ? jsx(RenderComponentInstall, {}) : jsx(RenderComponentNotify, {}) })));
}
function RenderComponentInstall() {
return jsx("div", __assign({ className: 'add-to-home-screen-pwa__notify', onClick: function () { return onCloseNotify(); } }, { children: jsx(Safari, { onClick: onInstallApp, translate: props.translate, styles: props.styles }) }));
}
function RenderComponentNotify() {
var ComponentNotify = null;
if ((initData === null || initData === void 0 ? void 0 : initData.platform) === 'chrome-android') {
ComponentNotify = jsx(Chrome, { translate: props.translate, styles: props.styles });
}
else if ((initData === null || initData === void 0 ? void 0 : initData.platform) === 'safari-iphone') {
ComponentNotify = jsx(Safari$1, { translate: props.translate, styles: props.styles });
}
return ComponentNotify ? jsx("div", __assign({ className: 'add-to-home-screen-pwa__notify', onClick: function () { return onCloseNotify(); } }, { children: ComponentNotify })) : null;
}
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(init, []);
// eslint-disable-next-line react-hooks/exhaustive-deps
useEffect(renderComponent, [initData, eventInstall]);
return jsx(Fragment, { children: component });
}
AddToHomeScreen.defaultProps = {
delayNotify: 0, skipFirstVisit: true, cookie: {}, translate: {}, styles: {}
};
AddToHomeScreen.propTypes = {
delayNotify: PropTypes.number,
skipFirstVisit: PropTypes.bool,
cookie: PropTypes.shape({ name: PropTypes.string, expireDays: PropTypes.number }),
translate: PropTypes.shape({
headline: PropTypes.string,
bottomline: PropTypes.string,
tapShare: PropTypes.string,
addHomeScreen: PropTypes.string,
chromiumInstruction: PropTypes.string,
chromiumInstall: PropTypes.string,
buttonInstall: PropTypes.string,
}),
styles: PropTypes.shape({
body: PropTypes.object,
button: PropTypes.object,
heading: PropTypes.object,
})
};
export { AddToHomeScreen };
//# sourceMappingURL=index.js.map