Clean up instructions
Test / test (push) Failing after 43s
Details
Test / test (push) Failing after 43s
Details
This commit is contained in:
parent
a62fd5ffdb
commit
987b419018
|
|
@ -3,6 +3,7 @@
|
|||
"tabWidth": 2,
|
||||
"semi": false,
|
||||
"singleQuote": false,
|
||||
"maxLineLength": 120,
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
import React from "react"
|
||||
import { useEffect } from "react"
|
||||
import { usePush } from "remix-pwa-monorepo/packages/push/client/hook"
|
||||
|
||||
export default function EnableNotifications({
|
||||
onSubscribe,
|
||||
}: {
|
||||
onSubscribe: () => void
|
||||
}) {
|
||||
return (
|
||||
<div>
|
||||
<h1>Allow Notifications</h1>
|
||||
<div>
|
||||
Tack Up Now requires your permission to send notifications in order to
|
||||
function properly
|
||||
</div>
|
||||
<EnableButton onSubscribe={onSubscribe} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function EnableButton({ onSubscribe }: { onSubscribe: () => void }) {
|
||||
const { subscribeToPush, requestPermission, canSendPush } = usePush()
|
||||
|
||||
function subscribe() {
|
||||
requestPermission()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!canSendPush) return
|
||||
|
||||
subscribeToPush(
|
||||
urlB64ToUint8Array(applicationServerPublicKey) as any,
|
||||
(subscription) => {
|
||||
fetch("/api/subscribe", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(subscription),
|
||||
})
|
||||
onSubscribe()
|
||||
}
|
||||
)
|
||||
}, [canSendPush])
|
||||
|
||||
return <button onClick={subscribe}>Enable Notifications</button>
|
||||
}
|
||||
|
||||
const applicationServerPublicKey =
|
||||
"BDTbzdtzJxwV0sscdsXla-GKvlcxqQr7edEfkX8-papwvvV1UVc3IMyRacl1BbgTi31nWPji2wKCZkjf1l5iX7Y"
|
||||
|
||||
function urlB64ToUint8Array(base64String: string) {
|
||||
const padding = "=".repeat((4 - (base64String.length % 4)) % 4)
|
||||
const base64 = (base64String + padding).replace(/\-/g, "+").replace(/_/g, "/")
|
||||
|
||||
const rawData = window.atob(base64)
|
||||
const outputArray = new Uint8Array(rawData.length)
|
||||
|
||||
for (let i = 0; i < rawData.length; ++i) {
|
||||
outputArray[i] = rawData.charCodeAt(i)
|
||||
}
|
||||
return outputArray
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import React from "react"
|
||||
|
||||
import shareIcon from "../../public/images/safari-share-icon.png"
|
||||
|
||||
export default function InstallPWA() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Install Tack Up Now!</h1>
|
||||
<div>
|
||||
Install Tack Up Now on your device to get notified when it's time to
|
||||
tack up
|
||||
</div>
|
||||
<div>
|
||||
<ul>
|
||||
<span>Tap </span>
|
||||
<img style={{ width: "2rem" }} src={shareIcon} />
|
||||
<span> and choose </span>
|
||||
<span className="bold">Add to Home Screen</span>
|
||||
</ul>
|
||||
<ul>
|
||||
<span>On the next screen, tap </span>
|
||||
<span className="bold">Add</span>
|
||||
</ul>
|
||||
<ul>
|
||||
<span>Then open </span>
|
||||
<span className="bold">Tack Up Now</span>
|
||||
<span> from your home screen</span>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
import React from "react"
|
||||
import useInstallState from "../useInstallState"
|
||||
import EnableNotifications from "./EnableNotifications"
|
||||
import OpenSafari from "./OpenSafari"
|
||||
import InstallPWA from "./InstallPWA"
|
||||
import Unsupported from "./Unsupported"
|
||||
|
||||
interface InstallPromptsProps {
|
||||
isMobileSafari: boolean
|
||||
isSupported: boolean
|
||||
notificationsEnabled: boolean
|
||||
onInstallComplete: () => void
|
||||
}
|
||||
|
||||
export default function InstallPrompts({
|
||||
isSupported,
|
||||
isMobileSafari,
|
||||
onInstallComplete,
|
||||
}: InstallPromptsProps) {
|
||||
const { step } = useInstallState({ isSupported, isMobileSafari })
|
||||
|
||||
const steps = {
|
||||
"open safari": <OpenSafari />,
|
||||
install: <InstallPWA />,
|
||||
"enable notifications": (
|
||||
<EnableNotifications onSubscribe={onInstallComplete} />
|
||||
),
|
||||
unsupported: <Unsupported />,
|
||||
}
|
||||
|
||||
return steps[step as keyof typeof steps] ?? null
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import React from "react"
|
||||
|
||||
export default function OpenSafari() {
|
||||
return (
|
||||
<div>
|
||||
<div>This device requires Tack Up Now to be installed using Safari</div>
|
||||
<br />
|
||||
<div>Open tackupnow.com in Safari to continue!</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
import React, { useState } from "react"
|
||||
|
||||
export default function Unsupported() {
|
||||
const [showWhy, setShowWhy] = useState(false)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>{"Sorry :("}</h1>
|
||||
<br />
|
||||
<div>Your device doesn't support Tack Up Now!</div>
|
||||
|
||||
{showWhy ? (
|
||||
<div>
|
||||
iOS 16.3 and under does not support notification delivery through web
|
||||
apps, so Tack Up Now can't send notifications to your device.
|
||||
</div>
|
||||
) : (
|
||||
<button onClick={() => setShowWhy(true)}>Why not?</button>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -7,6 +7,10 @@ import {
|
|||
} from "@remix-run/react"
|
||||
import React from "react"
|
||||
import { ManifestLink } from "@remix-pwa/sw"
|
||||
import { LinksFunction } from "@remix-run/node"
|
||||
import styles from "./styles/styles.css?url"
|
||||
|
||||
export const links: LinksFunction = () => [{ rel: "stylesheet", href: styles }]
|
||||
|
||||
export function Layout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ import React, { Suspense, useEffect, useState } from "react"
|
|||
import coerceSemver from "semver/functions/coerce"
|
||||
import versionAtLeast from "semver/functions/gte"
|
||||
import UAParser from "ua-parser-js"
|
||||
import { usePush } from "remix-pwa-monorepo/packages/push/client/hook"
|
||||
import InstallPrompts from "../install/InstallPrompts"
|
||||
import useInstallState from "../useInstallState"
|
||||
|
||||
export const meta: MetaFunction = () => {
|
||||
return [
|
||||
|
|
@ -21,25 +22,24 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
|
|||
const userAgent = request.headers.get("user-agent")
|
||||
const parsedUserAgent = new UAParser(userAgent ?? "")
|
||||
const os = parsedUserAgent.getOS()
|
||||
const isNonSafari = parsedUserAgent.getBrowser().name !== "Mobile Safari"
|
||||
const browser = parsedUserAgent.getBrowser().name
|
||||
const isMobileSafari = parsedUserAgent.getBrowser().name !== "Mobile Safari"
|
||||
const isSupported =
|
||||
os.name !== "iOS" ||
|
||||
versionAtLeast(coerceSemver(os.version) ?? "0.0.0", "16.4.0")
|
||||
|
||||
console.log("Wut", isNonSafari)
|
||||
|
||||
return json({ isSupported, isNonSafari, browser })
|
||||
return json({ isSupported, isMobileSafari })
|
||||
}
|
||||
|
||||
export default function Index() {
|
||||
const { isSupported, isNonSafari, browser } = useLoaderData<typeof loader>()
|
||||
const { isSupported, isMobileSafari } = useLoaderData<typeof loader>()
|
||||
|
||||
return (
|
||||
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
|
||||
<Suspense>
|
||||
<LandingMessage isSupported={isSupported} isNonSafari={isNonSafari} />
|
||||
{browser}
|
||||
<LandingMessage
|
||||
isSupported={isSupported}
|
||||
isMobileSafari={isMobileSafari}
|
||||
/>
|
||||
</Suspense>
|
||||
</div>
|
||||
)
|
||||
|
|
@ -47,86 +47,30 @@ export default function Index() {
|
|||
|
||||
function LandingMessage({
|
||||
isSupported,
|
||||
isNonSafari,
|
||||
isMobileSafari,
|
||||
}: {
|
||||
isSupported: boolean
|
||||
isNonSafari: boolean
|
||||
isMobileSafari: boolean
|
||||
}) {
|
||||
const isClient = typeof window !== "undefined"
|
||||
const notificationsEnabled =
|
||||
isClient &&
|
||||
"Notification" in window &&
|
||||
window.Notification.permission === "granted"
|
||||
|
||||
const isRunningPWA =
|
||||
isClient &&
|
||||
(("standalone" in navigator && (navigator.standalone as boolean)) ||
|
||||
matchMedia("(dislay-mode: standalone)").matches)
|
||||
const { installed } = useInstallState({ isSupported, isMobileSafari })
|
||||
|
||||
const [rendered, setRendered] = useState(false)
|
||||
const [isInstalled, setIsInstalled] = useState(notificationsEnabled)
|
||||
const [isInstalled, setIsInstalled] = useState(installed)
|
||||
|
||||
useEffect(() => {
|
||||
setRendered(true)
|
||||
}, [])
|
||||
|
||||
return !isClient || !rendered ? (
|
||||
return !rendered ? (
|
||||
<div>Loading</div>
|
||||
) : isInstalled ? (
|
||||
<div>Your Notifications</div>
|
||||
) : isNonSafari ? (
|
||||
<div>Safari</div>
|
||||
) : isRunningPWA && !notificationsEnabled ? (
|
||||
<EnableButton onSubscribe={() => setIsInstalled(true)} />
|
||||
) : isSupported ? (
|
||||
<div>Install Tack Up Now!</div>
|
||||
) : (
|
||||
<div>{"Sorry, your device doesn't support Tack Up Now! :("}</div>
|
||||
<InstallPrompts
|
||||
isMobileSafari={isMobileSafari}
|
||||
isSupported={isSupported}
|
||||
notificationsEnabled={false}
|
||||
onInstallComplete={() => setIsInstalled(true)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function EnableButton({ onSubscribe }: { onSubscribe: () => void }) {
|
||||
const { subscribeToPush, requestPermission, canSendPush } = usePush()
|
||||
|
||||
function subscribe() {
|
||||
requestPermission()
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (!canSendPush) return
|
||||
|
||||
subscribeToPush(
|
||||
urlB64ToUint8Array(applicationServerPublicKey) as any,
|
||||
(subscription) => {
|
||||
fetch("/api/subscribe", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(subscription),
|
||||
})
|
||||
onSubscribe()
|
||||
},
|
||||
(error) => {
|
||||
const errorDiv = document.createElement("div")
|
||||
errorDiv.innerText = "Error thingy" + JSON.stringify(error)
|
||||
document.appendChild(errorDiv)
|
||||
}
|
||||
)
|
||||
}, [canSendPush])
|
||||
|
||||
return <button onClick={subscribe}>Enable notifications</button>
|
||||
}
|
||||
|
||||
const applicationServerPublicKey =
|
||||
"BDTbzdtzJxwV0sscdsXla-GKvlcxqQr7edEfkX8-papwvvV1UVc3IMyRacl1BbgTi31nWPji2wKCZkjf1l5iX7Y"
|
||||
|
||||
function urlB64ToUint8Array(base64String: string) {
|
||||
const padding = "=".repeat((4 - (base64String.length % 4)) % 4)
|
||||
const base64 = (base64String + padding).replace(/\-/g, "+").replace(/_/g, "/")
|
||||
|
||||
const rawData = window.atob(base64)
|
||||
const outputArray = new Uint8Array(rawData.length)
|
||||
|
||||
for (let i = 0; i < rawData.length; ++i) {
|
||||
outputArray[i] = rawData.charCodeAt(i)
|
||||
}
|
||||
return outputArray
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import { usePush } from "remix-pwa-monorepo/packages/push/client/hook"
|
||||
|
||||
type IOSInstallStep =
|
||||
| "loading"
|
||||
| "install"
|
||||
| "open safari"
|
||||
| "enable notifications"
|
||||
| "unsupported"
|
||||
|
||||
export default function useInstallState({
|
||||
isSupported,
|
||||
isMobileSafari,
|
||||
}: {
|
||||
isSupported: boolean
|
||||
isMobileSafari: boolean
|
||||
}) {
|
||||
const isClient = typeof window !== undefined
|
||||
|
||||
if (!isClient)
|
||||
return {
|
||||
step: isSupported ? "loading" : ("unsupported" as IOSInstallStep),
|
||||
installed: false,
|
||||
}
|
||||
|
||||
const { canSendPush } = usePush()
|
||||
|
||||
const notificationsEnabled =
|
||||
("Notification" in window &&
|
||||
window.Notification.permission === "granted") ||
|
||||
canSendPush
|
||||
|
||||
const isRunningPWA =
|
||||
("standalone" in navigator && (navigator.standalone as boolean)) ||
|
||||
matchMedia("(dislay-mode: standalone)").matches
|
||||
|
||||
return {
|
||||
step: !isMobileSafari
|
||||
? "open safari"
|
||||
: !isRunningPWA && isMobileSafari
|
||||
? "install"
|
||||
: !notificationsEnabled
|
||||
? "enable notifications"
|
||||
: (null as IOSInstallStep | null),
|
||||
installed: notificationsEnabled,
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.6 KiB |
Loading…
Reference in New Issue