PWA
@@ -4,6 +4,13 @@ import { i18nLoader } from "./modules/i18n";
|
||||
import i18next from "i18next";
|
||||
import { I18nextProvider } from "react-i18next";
|
||||
|
||||
if ("serviceWorker" in navigator) {
|
||||
window.addEventListener("load", () => {
|
||||
// we will register it after the page complete the load
|
||||
void navigator.serviceWorker.register("/sw.js");
|
||||
});
|
||||
}
|
||||
|
||||
i18nLoader()
|
||||
.then(() =>
|
||||
hydrateRoot(
|
||||
|
||||
220
app/root.tsx
@@ -57,8 +57,10 @@ export const meta: MetaFunction = () => ({
|
||||
title: "sendou.ink",
|
||||
description:
|
||||
"Competitive Splatoon Hub featuring gear planner, event calendar, builds by top players, and more!",
|
||||
viewport: "width=device-width,initial-scale=1",
|
||||
"theme-color": "#02011e",
|
||||
viewport: "initial-scale=1, viewport-fit=cover, user-scalable=no",
|
||||
"apple-mobile-web-app-status-bar-style": "black-translucent",
|
||||
"apple-mobile-web-app-capable": "yes",
|
||||
"theme-color": "#010115",
|
||||
"og:image": COMMON_PREVIEW_IMAGE,
|
||||
});
|
||||
|
||||
@@ -125,6 +127,8 @@ function Document({
|
||||
<head>
|
||||
<Meta />
|
||||
<Links />
|
||||
<link rel="manifest" href="/app.webmanifest" />
|
||||
<PWALinks />
|
||||
<Fonts />
|
||||
</head>
|
||||
<body>
|
||||
@@ -141,23 +145,6 @@ function Document({
|
||||
);
|
||||
}
|
||||
|
||||
function Fonts() {
|
||||
return (
|
||||
<>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link
|
||||
rel="preconnect"
|
||||
href="https://fonts.gstatic.com"
|
||||
crossOrigin="true"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Lexend:wght@400;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: this should be an array if we can figure out how to make Typescript
|
||||
// enforce that it has every member of keyof CustomTypeOptions["resources"] without duplicating the type manually
|
||||
export const namespaceJsonsToPreloadObj: Record<
|
||||
@@ -214,3 +201,198 @@ export const ErrorBoundary: ErrorBoundaryComponent = ({ error }) => {
|
||||
</Document>
|
||||
);
|
||||
};
|
||||
|
||||
function Fonts() {
|
||||
return (
|
||||
<>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link
|
||||
rel="preconnect"
|
||||
href="https://fonts.gstatic.com"
|
||||
crossOrigin="true"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Lexend:wght@400;600;700&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function PWALinks() {
|
||||
return (
|
||||
<>
|
||||
<link rel="apple-touch-icon" href="/static-assets/img/app-icon.png" />
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/iPhone_14_Pro_Max_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/iPhone_14_Pro_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/iPhone_14_Plus__iPhone_13_Pro_Max__iPhone_12_Pro_Max_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/iPhone_14__iPhone_13_Pro__iPhone_13__iPhone_12_Pro__iPhone_12_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/iPhone_13_mini__iPhone_12_mini__iPhone_11_Pro__iPhone_XS__iPhone_X_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/iPhone_11_Pro_Max__iPhone_XS_Max_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/iPhone_11__iPhone_XR_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/iPhone_8_Plus__iPhone_7_Plus__iPhone_6s_Plus__iPhone_6_Plus_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/iPhone_8__iPhone_7__iPhone_6s__iPhone_6__4.7__iPhone_SE_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/4__iPhone_SE__iPod_touch_5th_generation_and_later_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/12.9__iPad_Pro_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/11__iPad_Pro__10.5__iPad_Pro_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/10.9__iPad_Air_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/10.5__iPad_Air_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/10.2__iPad_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/9.7__iPad_Pro__7.9__iPad_mini__9.7__iPad_Air__9.7__iPad_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)"
|
||||
href="/static-assets/img/splash-screens/8.3__iPad_Mini_landscape.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/iPhone_14_Pro_Max_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/iPhone_14_Pro_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/iPhone_14_Plus__iPhone_13_Pro_Max__iPhone_12_Pro_Max_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/iPhone_14__iPhone_13_Pro__iPhone_13__iPhone_12_Pro__iPhone_12_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/iPhone_13_mini__iPhone_12_mini__iPhone_11_Pro__iPhone_XS__iPhone_X_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/iPhone_11_Pro_Max__iPhone_XS_Max_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/iPhone_11__iPhone_XR_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/iPhone_8_Plus__iPhone_7_Plus__iPhone_6s_Plus__iPhone_6_Plus_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/iPhone_8__iPhone_7__iPhone_6s__iPhone_6__4.7__iPhone_SE_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/4__iPhone_SE__iPod_touch_5th_generation_and_later_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/12.9__iPad_Pro_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/11__iPad_Pro__10.5__iPad_Pro_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/10.9__iPad_Air_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/10.5__iPad_Air_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/10.2__iPad_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/9.7__iPad_Pro__7.9__iPad_mini__9.7__iPad_Air__9.7__iPad_portrait.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-startup-image"
|
||||
media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)"
|
||||
href="/static-assets/img/splash-screens/8.3__iPad_Mini_portrait.png"
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ body {
|
||||
-moz-osx-font-smoothing: antialiased;
|
||||
line-height: 1.55;
|
||||
overflow-x: hidden;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
*:focus:not(:focus-visible) {
|
||||
|
||||
@@ -256,6 +256,17 @@
|
||||
background-color: var(--theme-transparent);
|
||||
}
|
||||
|
||||
@media screen and (display-mode: standalone) {
|
||||
.layout__header {
|
||||
height: 80px;
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.layout__main {
|
||||
padding-block-start: var(--s-26);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 900px) {
|
||||
.layout__side-nav {
|
||||
display: none;
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
--s-16: 4rem;
|
||||
--s-20: 5rem;
|
||||
--s-24: 6rem;
|
||||
--s-26: 6.5rem;
|
||||
--s-28: 7rem;
|
||||
--s-32: 8rem;
|
||||
--s-40: 10rem;
|
||||
|
||||
51
public/app.webmanifest
Normal file
@@ -0,0 +1,51 @@
|
||||
{
|
||||
"name": "sendou.ink",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"id": "sendou.ink",
|
||||
"description": "Competitive Splatoon Hub",
|
||||
"theme_color": "#010115",
|
||||
"background_color": "#02011e",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static-assets/img/app-icon.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"shortcuts": [
|
||||
{
|
||||
"name": "Builds",
|
||||
"url": "/builds",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static-assets/img/pwa-icons/builds.png",
|
||||
"type": "image/png",
|
||||
"sizes": "96x96"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Build Analyzer",
|
||||
"url": "/analyzer",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static-assets/img/pwa-icons/analyzer.png",
|
||||
"type": "image/png",
|
||||
"sizes": "96x96"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Calendar",
|
||||
"url": "/calendar",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/static-assets/img/pwa-icons/calendar.png",
|
||||
"type": "image/png",
|
||||
"sizes": "96x96"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
public/static-assets/img/app-icon.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/static-assets/img/pwa-icons/analyzer.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/static-assets/img/pwa-icons/builds.png
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
public/static-assets/img/pwa-icons/calendar.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/static-assets/img/splash-screens/10.2__iPad_landscape.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
public/static-assets/img/splash-screens/10.2__iPad_portrait.png
Normal file
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 85 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 82 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 68 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 73 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 31 KiB |
3
public/sw.js
Normal file
@@ -0,0 +1,3 @@
|
||||
self.addEventListener("fetch", function () {
|
||||
return;
|
||||
});
|
||||