Skip to content

Commit

Permalink
added pwa prompt to homescreen
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephen-Gordon committed Mar 19, 2024
1 parent a34cbd1 commit 4214265
Show file tree
Hide file tree
Showing 14 changed files with 521 additions and 54 deletions.
42 changes: 35 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"axios": "^1.6.7",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.0",
"cookies-next": "^4.1.1",
"date-fns": "^3.3.1",
"ethers": "5.7",
"framer-motion": "^11.0.8",
Expand All @@ -59,7 +60,7 @@
"react-circular-progressbar": "^2.1.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.51.0",
"react-ios-pwa-prompt": "^1.8.4",
"react-icons": "^5.0.1",
"react-modal-sheet": "^2.2.0",
"react-pull-to-refresh": "^2.0.1",
"react-qr-code": "^2.0.12",
Expand Down
Binary file added src/app/assets/img/icons/firefox-install.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
96 changes: 96 additions & 0 deletions src/app/components/AddToHomeScreen/AddToHomeScreen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { useState, useEffect } from 'react';
import { setCookie, getCookie } from 'cookies-next';
import dynamic from 'next/dynamic';

const ModuleLoading = () => <p className="animate-bounce text-white font-bold">Loading...</p>;
const AddToIosSafari = dynamic(() => import('./AddToIosSafari'), { loading: () => <ModuleLoading /> });
const AddToMobileChrome = dynamic(() => import('./AddToMobileChrome'), { loading: () => <ModuleLoading /> });
const AddToMobileFirefox = dynamic(() => import('./AddToMobileFirefox'), { loading: () => <ModuleLoading /> });
const AddToMobileFirefoxIos = dynamic(() => import('./AddToMobileFirefoxIos'), { loading: () => <ModuleLoading /> });
const AddToMobileChromeIos = dynamic(() => import('./AddToMobileChromeIos'), { loading: () => <ModuleLoading /> });
const AddToSamsung = dynamic(() => import('./AddToSamsung'), { loading: () => <ModuleLoading /> });
const AddToOtherBrowser = dynamic(() => import('./AddToOtherBrowser'), { loading: () => <ModuleLoading /> });

import useUserAgent from '@/app/hooks/useUserAgent';

type AddToHomeScreenPromptType = 'safari' | 'chrome' | 'firefox' | 'other' | 'firefoxIos' | 'chromeIos' | 'samsung' | '';
const COOKIE_NAME = 'addToHomeScreenPrompt';

export default function AddToHomeScreen() {
const [displayPrompt, setDisplayPrompt] = useState<AddToHomeScreenPromptType>('');
const { userAgent, isMobile, isStandalone, isIOS } = useUserAgent();

const closePrompt = () => {
setDisplayPrompt('');
};

const doNotShowAgain = () => {
// Create date 1 year from now
const date = new Date();
date.setFullYear(date.getFullYear() + 1);
setCookie(COOKIE_NAME, 'dontShow', { expires: date }); // Set cookie for a year
setDisplayPrompt('');
};

useEffect(() => {
const addToHomeScreenPromptCookie = getCookie(COOKIE_NAME);

if (addToHomeScreenPromptCookie !== 'dontShow') {
// Only show prompt if user is on mobile and app is not installed
if (isMobile && !isStandalone) {
if (userAgent === 'Safari') {
setDisplayPrompt('safari');
} else if (userAgent === 'Chrome') {
setDisplayPrompt('chrome');
} else if (userAgent === 'Firefox') {
setDisplayPrompt('firefox');
} else if (userAgent === 'FirefoxiOS') {
setDisplayPrompt('firefoxIos');
} else if (userAgent === 'ChromeiOS') {
setDisplayPrompt('chromeIos');
} else if (userAgent === 'SamsungBrowser') {
setDisplayPrompt('samsung');
} else {
setDisplayPrompt('other');
}
}
} else {
}
}, [userAgent, isMobile, isStandalone, isIOS]);

const Prompt = () => (
<>
{
{
'safari': <AddToIosSafari closePrompt={closePrompt} doNotShowAgain={doNotShowAgain} />,
'chrome': <AddToMobileChrome closePrompt={closePrompt} doNotShowAgain={doNotShowAgain} />,
'firefox': <AddToMobileFirefox closePrompt={closePrompt} doNotShowAgain={doNotShowAgain} />,
'firefoxIos': <AddToMobileFirefoxIos closePrompt={closePrompt} doNotShowAgain={doNotShowAgain} />,
'chromeIos': <AddToMobileChromeIos closePrompt={closePrompt} doNotShowAgain={doNotShowAgain} />,
'samsung': <AddToSamsung closePrompt={closePrompt} doNotShowAgain={doNotShowAgain} />,
'other': <AddToOtherBrowser closePrompt={closePrompt} doNotShowAgain={doNotShowAgain} />,
'': <></>
}[displayPrompt]
}
</>
)

return (
<>
{
displayPrompt !== ''
?
<>
<div
className="fixed top-0 left-0 right-0 bottom-0 bg-black/70 z-50"
onClick={closePrompt}
>
<Prompt />
</div>
</>
:
<></>
}
</>
);
}
43 changes: 43 additions & 0 deletions src/app/components/AddToHomeScreen/AddToIosSafari.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react'

import { TbShare2 } from 'react-icons/tb'
import { AiOutlinePlusSquare } from 'react-icons/ai'
import { FaTimes } from 'react-icons/fa'
import { ImArrowDown } from 'react-icons/im'

interface Props {
closePrompt: () => void;
doNotShowAgain: () => void;
}

export default function AddToIosSafari(props: Props) {
const { closePrompt, doNotShowAgain } = props;

return (
<div className="fixed bottom-0 left-0 right-0 h-[60%] z-50 pb-12 px-4 text-white">
<div className="relative bg-primary p-4 h-full rounded-xl flex flex-col justify-around items-center text-center">
<button className="absolute top-0 right-0 p-3" onClick={closePrompt}>
<FaTimes className="text-2xl" />
</button>
<p className="text-lg">For the best experience, we recommend installing the Valley Trader app to your home screen!</p>
<div className="flex gap-2 items-center text-lg">
<p>Click the</p>
<TbShare2 className="text-4xl" />
<p>icon</p>
</div>
<div className="flex flex-col gap-2 items-center text-lg w-full px-4">
<p>Scroll down and then click:</p>
<div className="bg-zinc-800 flex justify-between items-center w-full px-4 py-2 rounded-lg">
<p>Add to Home Screen</p>
<AiOutlinePlusSquare className="text-2xl" />
</div>
</div>
<button className="border-2 p-1" onClick={doNotShowAgain}>Don&apos;t show again</button>
<ImArrowDown
className="text-4xl absolute -bottom-[50px] text-indigo-700 -z-10 animate-bounce"
/>
</div>

</div>
)
}
40 changes: 40 additions & 0 deletions src/app/components/AddToHomeScreen/AddToMobileChrome.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react'

import { FaTimes } from 'react-icons/fa'
import { HiDotsVertical } from 'react-icons/hi'
import { MdAddToHomeScreen } from 'react-icons/md'
import { ImArrowUp } from 'react-icons/im'

interface Props {
closePrompt: () => void;
doNotShowAgain: () => void;
}

export default function AddToMobileChrome(props: Props) {
const { closePrompt, doNotShowAgain } = props;

return (
<div className="fixed top-0 left-0 right-0 h-[60%] z-50 pt-12 px-4 text-white">
<ImArrowUp className="text-4xl absolute top-[10px] right-[10px] text-indigo-700 z-10 animate-bounce" />
<div className="relative bg-primary p-4 h-full rounded-xl flex flex-col justify-around items-center text-center">
<button className="absolute top-0 right-0 p-3" onClick={closePrompt}>
<FaTimes className="text-2xl" />
</button>
<p className="text-lg">For the best experience, we recommend installing the Valley Trader app to your home screen!</p>
<div className="flex gap-2 items-center text-lg">
<p>Click the</p>
<HiDotsVertical className="text-4xl" />
<p>icon</p>
</div>
<div className="flex flex-col gap-2 items-center text-lg w-full px-4">
<p>Scroll down and then click:</p>
<div className="bg-zinc-50 flex justify-between items-center w-full px-4 py-2 rounded-lg text-zinc-900">
<MdAddToHomeScreen className="text-2xl" />
<p>Add to Home Screen</p>
</div>
</div>
<button className="border-2 p-1" onClick={doNotShowAgain}>Don&apos;t show again</button>
</div>
</div>
)
}
41 changes: 41 additions & 0 deletions src/app/components/AddToHomeScreen/AddToMobileChromeIos.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from 'react'

import { AiOutlinePlusSquare } from 'react-icons/ai'
import { FaTimes } from 'react-icons/fa'
import { ImArrowUp } from 'react-icons/im'
import { TbShare2 } from 'react-icons/tb'

interface Props {
closePrompt: () => void;
doNotShowAgain: () => void;
}

export default function AddToMobileChromeIos(props: Props) {
const { closePrompt, doNotShowAgain } = props;

return (
<div className="fixed top-0 left-0 right-0 h-[70%] z-50 pt-12 px-4 text-white">
<div className="relative bg-primary p-4 h-full rounded-xl flex flex-col justify-around items-center text-center">
<ImArrowUp className="text-4xl absolute -top-[40px] right-0 text-indigo-700 z-10 animate-bounce" />
<button className="absolute top-0 right-0 p-3" onClick={closePrompt}>
<FaTimes className="text-2xl" />
</button>
<p className="text-lg">For the best experience, we recommend installing the Valley Trader app to your home screen!</p>
<div className="flex gap-2 items-center text-lg">
<p>Click the</p>
<TbShare2 className="text-4xl" />
<p>icon</p>
</div>
<div className="flex flex-col gap-2 items-center text-lg w-full px-4">
<p>Scroll down and then click:</p>
<div className="bg-zinc-800 flex items-center justify-between w-full px-8 py-2 rounded-lg">
<p>Add to Home Screen</p>
<AiOutlinePlusSquare className="text-2xl" />
</div>
</div>
<button className="border-2 p-1" onClick={doNotShowAgain}>Don&apos;t show again</button>
</div>

</div>
)
}
44 changes: 44 additions & 0 deletions src/app/components/AddToHomeScreen/AddToMobileFirefox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react'
import Image from 'next/image'

import { FaTimes } from 'react-icons/fa'
import { HiDotsVertical } from 'react-icons/hi'
import { ImArrowDownRight } from 'react-icons/im'
import ffIcon from '@/app/assets/img/icons/firefox-install.png'

interface Props {
closePrompt: () => void;
doNotShowAgain: () => void;
}

export default function AddToMobileFirefox(props: Props) {
const { closePrompt, doNotShowAgain } = props;

return (
<div className="fixed bottom-0 left-0 right-0 h-[60%] z-50 pb-12 px-4 text-white">
<div className="relative bg-primary p-4 h-full rounded-xl flex flex-col justify-around items-center text-center">
<button className="absolute top-0 right-0 p-3" onClick={closePrompt}>
<FaTimes className="text-2xl" />
</button>
<p className="text-lg">For the best experience, we recommend installing the Valley Trader app to your home screen!</p>
<div className="flex gap-2 items-center text-lg">
<p>Click the</p>
<HiDotsVertical className="text-4xl" />
<p>icon</p>
</div>
<div className="flex flex-col gap-2 items-center text-lg w-full px-4">
<p>Scroll down and then click:</p>
<div className="bg-zinc-50 flex items-center justify-around w-full px-4 py-2 rounded-lg text-zinc-900">
<div className="flex gap-6 items-center">
<Image src={ffIcon} alt="Firefox install icon" width={32} height={32} />
<p>Install</p>
</div>
</div>
</div>
<button className="border-2 p-1" onClick={doNotShowAgain}>Don&apos;t show again</button>
<ImArrowDownRight className="text-4xl absolute -bottom-[50px] right-1 text-indigo-700 z-10 animate-bounce" />
</div>

</div>
)
}
Loading

0 comments on commit 4214265

Please sign in to comment.