1
0
mirror of https://github.com/barthuijgen/factorio-sites.git synced 2025-03-17 21:17:57 +02:00

Added different renderer for mobile

This commit is contained in:
Bart 2021-03-18 14:01:56 +01:00
parent 95728d0000
commit bcf796417e
9 changed files with 211 additions and 57 deletions

View File

@ -14,7 +14,6 @@ const DropdownBox = styled(Box)`
transform: translateY(100%);
bottom: -0.5rem;
right: 40px;
z-index: 3;
`;
export const CopyButtonDropdown: React.FC = (props) => {

View File

@ -1,6 +1,24 @@
import React, { useState } from "react";
import { css } from "@emotion/react";
import { MapInteractionCSS } from "react-map-interaction";
import { Image } from "@chakra-ui/image";
import styled from "@emotion/styled";
import { Box } from "@chakra-ui/react";
const StyledImage = styled(Box)`
display: flex;
justify-content: center;
img {
max-width: 100%;
max-height: 500px;
object-fit: contain;
}
img:hover {
cursor: pointer;
}
`;
const elementStyle = css`
display: flex;
@ -12,6 +30,8 @@ const elementStyle = css`
padding: 0px;
background: rgba(0, 0, 0, 0.5);
justify-content: center;
z-index: 1;
& > div > div {
display: flex;
justify-content: center;
@ -21,34 +41,50 @@ const elementStyle = css`
interface FullscreenImageProps {
alt: string;
src: string;
close: () => void;
close?: () => void;
}
export const FullscreenImage: React.FC<FullscreenImageProps> = ({ alt, src, close }) => {
export const FullscreenImage: React.FC<FullscreenImageProps> = ({ alt, src }) => {
const [open, setOpen] = useState(false);
const [state, setState] = useState({
scale: 0.9,
translation: { x: window.innerWidth * 0.05, y: 30 },
});
console.log(src);
return (
<div
css={elementStyle}
onClick={(e) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((e as any).target.nodeName.toUpperCase() !== "IMG") {
close();
}
}}
onTouchEnd={(e) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((e as any).target.nodeName.toUpperCase() !== "IMG") {
close();
}
}}
>
<MapInteractionCSS value={state} onChange={setState}>
<img alt={alt} src={src} />
</MapInteractionCSS>
</div>
<>
<StyledImage>
<Image
src={src}
alt={alt}
maxWidth="100%"
maxHeight="500px"
objectFit="contain"
onClick={() => setOpen(true)}
/>
</StyledImage>
{open && (
<div
css={elementStyle}
onClick={(e) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((e as any).target.nodeName.toUpperCase() !== "IMG") {
setOpen(false);
}
}}
onTouchEnd={(e) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
if ((e as any).target.nodeName.toUpperCase() !== "IMG") {
setOpen(false);
}
}}
>
<MapInteractionCSS value={state} onChange={setState}>
<img alt={alt} src={src} />
</MapInteractionCSS>
</div>
)}
</>
);
};

View File

@ -13,6 +13,9 @@ import { BlueprintData } from "./BlueprintData";
import { BlueprintInfo } from "./BlueprintInfo";
import { BlueprintTags } from "./BlueprintTags";
import { BlueprintEntities } from "./BlueprintEntities";
import { useCookies } from "react-cookie";
import { FullscreenImage } from "../FullscreenImage";
import { isMobileBrowser } from "../../utils/navigator.utils";
const StyledBlueptintPage = styled(Grid)`
grid-gap: 16px;
@ -55,6 +58,8 @@ export const BlueprintSubPage: React.FC<BlueprintProps> = ({
const url = useUrl();
const [string, setString] = useState<string | null>(null);
const [data, setData] = useState<BlueprintStringData | null>(null);
const [cookies] = useCookies();
const isFbeRenderer = cookies.renderer !== "fbsr" && !isMobileBrowser();
useEffect(() => {
fetch(`/api/string/${blueprint.blueprint_hash}`)
@ -79,11 +84,13 @@ export const BlueprintSubPage: React.FC<BlueprintProps> = ({
title={
<>
<span>Image</span>
<img
src="/fbe.svg"
alt="Factorio blueprint editor"
css={{ display: "inline-block", height: "24px", marginLeft: "10px" }}
/>
{isFbeRenderer && (
<img
src="/fbe.svg"
alt="Factorio blueprint editor"
css={{ display: "inline-block", height: "24px", marginLeft: "10px" }}
/>
)}
<Box css={{ display: "inline-block", flexGrow: 1, textAlign: "right" }}>
{string && (
<CopyButton
@ -103,7 +110,15 @@ export const BlueprintSubPage: React.FC<BlueprintProps> = ({
</>
}
>
{string && <ImageEditor string={string}></ImageEditor>}
{string &&
(isFbeRenderer ? (
<ImageEditor string={string}></ImageEditor>
) : (
<FullscreenImage
src={`https://fbsr.factorio.workers.dev/${blueprint.blueprint_hash}?size=1000`}
alt={blueprint.label}
/>
))}
</Panel>
<Panel

View File

@ -25,6 +25,9 @@ import { BlueprintInfo } from "./BlueprintInfo";
import { BlueprintTags } from "./BlueprintTags";
import { BlueprintEntities } from "./BlueprintEntities";
import { FactorioCode } from "../FactorioCode";
import { useCookies } from "react-cookie";
import { FullscreenImage } from "../FullscreenImage";
import { isMobileBrowser } from "../../utils/navigator.utils";
const StyledBlueptintPage = styled(Grid)`
grid-gap: 16px;
@ -76,6 +79,8 @@ export const BlueprintBookSubPage: React.FC<BlueprintBookSubPageProps> = ({
null
);
const [selectedData, setSelectedData] = useState<BlueprintStringData | null>(null);
const [cookies] = useCookies();
const isFbeRenderer = cookies.renderer !== "fbsr" && !isMobileBrowser();
const selectedHash = selected.data.blueprint_hash;
const showEntities = selected.type === "blueprint" && selectedData?.blueprint;
@ -158,11 +163,13 @@ export const BlueprintBookSubPage: React.FC<BlueprintBookSubPageProps> = ({
title={
<>
<span>Image</span>
<img
src="/fbe.svg"
alt="Factorio blueprint editor"
css={{ display: "inline-block", height: "24px", marginLeft: "10px" }}
/>
{isFbeRenderer && (
<img
src="/fbe.svg"
alt="Factorio blueprint editor"
css={{ display: "inline-block", height: "24px", marginLeft: "10px" }}
/>
)}
<Box css={{ display: "inline-block", flexGrow: 1, textAlign: "right" }}>
{selectedBlueprintString && (
<CopyButton
@ -182,7 +189,17 @@ export const BlueprintBookSubPage: React.FC<BlueprintBookSubPageProps> = ({
</>
}
>
{selectedBlueprintString && <ImageEditor string={selectedBlueprintString}></ImageEditor>}
{selectedBlueprintString &&
(isFbeRenderer ? (
<ImageEditor string={selectedBlueprintString}></ImageEditor>
) : (
<FullscreenImage
src={`https://fbsr.factorio.workers.dev/${selected.data.blueprint_hash}?size=1000`}
alt={selected.data.label}
/>
))}
{/* {selectedBlueprintString && <ImageEditor string={selectedBlueprintString}></ImageEditor>} */}
</Panel>
<Panel

View File

@ -4,10 +4,11 @@ import Router from "next/router";
import { css, Global } from "@emotion/react";
import { ChakraProvider } from "@chakra-ui/react";
import NProgress from "nprogress";
import { CookiesProvider } from "react-cookie";
import { getSessionToken } from "@factorio-sites/node-utils";
import { Header } from "../components/Header";
import { AuthContext, AuthContextProps } from "../providers/auth";
import { useFetch } from "../hooks/fetch";
import { getSessionToken } from "@factorio-sites/node-utils";
const globalStyles = css`
@font-face {
@ -59,7 +60,7 @@ if (typeof window !== "undefined") {
speed: 800,
trickleSpeed: 150,
template:
'<div class="bar" role="bar" style="background: #00a1ff;position: fixed;z-index: 1031;top: 0;left: 0;width: 100%;height: 4px;" />',
'<div class="bar" role="bar" style="background: #00a1ff;position: fixed;z-index: 5;top: 0;left: 0;width: 100%;height: 4px;" />',
});
Router.events.on("routeChangeStart", () => NProgress.start());
Router.events.on("routeChangeComplete", () => NProgress.done());
@ -75,24 +76,26 @@ const BlueprintsApp = ({
return (
<ChakraProvider>
<AuthContext.Provider value={auth.data?.auth || null}>
<Global styles={globalStyles} />
<Head>
<title>Factorio Blueprints</title>
<link rel="shortcut icon" href="/favicon.png" />
<meta name="description" content="Find blueprints for Factorio with advanced search" />
</Head>
{!auth.loading && (
<>
<Header />
<main>
<div className="container">
<Component {...pageProps} />
</div>
</main>
</>
)}
</AuthContext.Provider>
<CookiesProvider>
<AuthContext.Provider value={auth.data?.auth || null}>
<Global styles={globalStyles} />
<Head>
<title>Factorio Blueprints</title>
<link rel="shortcut icon" href="/favicon.png" />
<meta name="description" content="Find blueprints for Factorio with advanced search" />
</Head>
{!auth.loading && (
<>
<Header />
<main>
<div className="container">
<Component {...pageProps} />
</div>
</main>
</>
)}
</AuthContext.Provider>
</CookiesProvider>
</ChakraProvider>
);
};

View File

@ -1,9 +1,20 @@
import React from "react";
import { NextPage } from "next";
import { useRouter } from "next/router";
import { FormControl, FormLabel, FormErrorMessage, Input, SimpleGrid } from "@chakra-ui/react";
import {
FormControl,
FormLabel,
FormErrorMessage,
Input,
SimpleGrid,
Radio,
Stack,
RadioGroup,
} from "@chakra-ui/react";
import { Formik, Field, FieldProps } from "formik";
import { addYears } from "date-fns";
import { css } from "@emotion/react";
import { useCookies } from "react-cookie";
import { Panel } from "../../components/Panel";
import { Button } from "../../components/Button";
import { validateUserForm } from "../../utils/validate";
@ -17,6 +28,7 @@ const FieldStyle = css`
export const UserEdit: NextPage = () => {
const auth = useAuth();
const router = useRouter();
const [cookies, setCookie] = useCookies(["renderer"]);
return (
<SimpleGrid columns={1} margin="0 auto" width="600px">
@ -72,6 +84,34 @@ export const UserEdit: NextPage = () => {
)}
</Field>
<Field name="renderer">
{({ field, meta }: FieldProps) => (
<FormControl
id="renderer"
isRequired={!auth?.steam_id}
isInvalid={meta.touched && !!meta.error}
css={FieldStyle}
>
<FormLabel>Image renderer</FormLabel>
<RadioGroup
onChange={(value: string) =>
setCookie("renderer", value, {
path: "/",
expires: addYears(new Date(), 1),
})
}
value={cookies.renderer || "fbe"}
>
<Stack>
<Radio value="fbe">FBE</Radio>
<Radio value="fbsr">FBSR</Radio>
</Stack>
</RadioGroup>
<FormErrorMessage>{meta.error}</FormErrorMessage>
</FormControl>
)}
</Field>
<Button
primary
css={{ width: 80, textAlign: "center" }}

View File

@ -0,0 +1,13 @@
export function isMobileBrowser() {
return (function (nav) {
return Boolean(
/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
nav
) ||
/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(
nav.substr(0, 4)
)
);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
})(navigator.userAgent || navigator.vendor || (window as any).opera);
}

View File

@ -54,6 +54,7 @@
"phin": "3.5.1",
"puppeteer": "8.0.0",
"react": "17.0.1",
"react-cookie": "4.0.3",
"react-dom": "17.0.1",
"react-icons": "4.2.0",
"react-map-interaction": "2.0.0",

View File

@ -4081,6 +4081,11 @@
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.0.tgz#14f854c0f93d326e39da6e3b6f34f7d37513d108"
integrity sha512-y7mImlc/rNkvCRmg8gC3/lj87S7pTUIJ6QGjwHR9WQJcFs+ZMTOaoPrkdFA/YdbuqVEmEbb5RdhVxMkAcgOnpg==
"@types/cookie@^0.3.3":
version "0.3.3"
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803"
integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==
"@types/duplexify@^3.6.0":
version "3.6.0"
resolved "https://registry.yarnpkg.com/@types/duplexify/-/duplexify-3.6.0.tgz#dfc82b64bd3a2168f5bd26444af165bf0237dcd8"
@ -4125,6 +4130,14 @@
dependencies:
"@types/node" "*"
"@types/hoist-non-react-statics@^3.0.1":
version "3.3.1"
resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
dependencies:
"@types/react" "*"
hoist-non-react-statics "^3.3.0"
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762"
@ -6442,7 +6455,7 @@ cookie@0.4.0:
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
cookie@0.4.1:
cookie@0.4.1, cookie@^0.4.0:
version "0.4.1"
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
@ -9065,7 +9078,7 @@ hmac-drbg@^1.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1:
hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@ -13477,6 +13490,15 @@ react-clientside-effect@^1.2.2:
dependencies:
"@babel/runtime" "^7.0.0"
react-cookie@4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/react-cookie/-/react-cookie-4.0.3.tgz#ba8e5ea0047c916516e1181a3ad394c9b7580b56"
integrity sha512-cmi6IpdVgTSvjqssqIEvo779Gfqc4uPGHRrKMEdHcqkmGtPmxolGfsyKj95bhdLEKqMdbX8MLBCwezlnhkHK0g==
dependencies:
"@types/hoist-non-react-statics" "^3.0.1"
hoist-non-react-statics "^3.0.0"
universal-cookie "^4.0.0"
react-dom@17.0.1:
version "17.0.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.1.tgz#1de2560474ec9f0e334285662ede52dbc5426fc6"
@ -15876,6 +15898,14 @@ unist-util-visit@^2.0.0:
unist-util-is "^4.0.0"
unist-util-visit-parents "^3.0.0"
universal-cookie@^4.0.0:
version "4.0.4"
resolved "https://registry.yarnpkg.com/universal-cookie/-/universal-cookie-4.0.4.tgz#06e8b3625bf9af049569ef97109b4bb226ad798d"
integrity sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==
dependencies:
"@types/cookie" "^0.3.3"
cookie "^0.4.0"
universalify@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"