tack-up-now/app/routes/_index.tsx

110 lines
3.2 KiB
TypeScript

import {
json,
type LoaderFunctionArgs,
type MetaFunction,
} from "@remix-run/node"
import { useLoaderData } from "@remix-run/react"
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"
export const meta: MetaFunction = () => {
return [
{ title: "Tack Up Now!" },
{ name: "description", content: "Get equinelive notifications" },
]
}
export const loader = async ({ request }: LoaderFunctionArgs) => {
const userAgent = request.headers.get("user-agent")
const os = new UAParser(userAgent ?? "").getOS()
const isSupported =
os.name !== "iOS" ||
versionAtLeast(coerceSemver(os.version) ?? "0.0.0", "16.4.0")
return json({ isSupported })
}
export default function Index() {
const { isSupported } = useLoaderData<typeof loader>()
return (
<div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
<Suspense>
<LandingMessage isSupported={isSupported} />
</Suspense>
</div>
)
}
function LandingMessage({ isSupported }: { isSupported: 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 [rendered, setRendered] = useState(false)
const [isInstalled, setIsInstalled] = useState(notificationsEnabled)
useEffect(() => {
setRendered(true)
}, [])
return !isClient || !rendered ? (
<div>Loading</div>
) : isInstalled ? (
<div>Your Notifications</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>
)
}
function EnableButton({ onSubscribe }: { onSubscribe: () => void }) {
const { subscribeToPush, requestPermission } = usePush()
return <button onClick={subscribe}>Enable notifications</button>
async function subscribe() {
console.log("Hey the thing was clicked wow")
await requestPermission()
subscribeToPush(
urlB64ToUint8Array(applicationServerPublicKey) as any,
(subscription) => {
fetch("/subscribe", {
method: "POST",
body: JSON.stringify(subscription),
})
onSubscribe()
}
)
}
}
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
}