From c4b9ba011d0e366f463e4a13c30dc430ed477b37 Mon Sep 17 00:00:00 2001 From: Guusvanmeerveld Date: Thu, 31 Mar 2022 23:50:09 +0200 Subject: [PATCH] Added more settings to /settings #5 --- next.config.js | 2 +- .../MaterialColorPicker/ColorBox.tsx | 20 + src/components/MaterialColorPicker/index.tsx | 103 +++++ src/components/ModalBox.ts | 17 + src/components/Navbar/index.tsx | 28 +- src/interfaces/settings.ts | 10 + src/pages/settings.tsx | 357 +++++++++++------- src/pages/trending.tsx | 2 +- src/utils/hooks.ts | 3 +- 9 files changed, 398 insertions(+), 144 deletions(-) create mode 100644 src/components/MaterialColorPicker/ColorBox.tsx create mode 100644 src/components/MaterialColorPicker/index.tsx create mode 100644 src/components/ModalBox.ts diff --git a/next.config.js b/next.config.js index c20c4e5..639e431 100644 --- a/next.config.js +++ b/next.config.js @@ -10,7 +10,7 @@ module.exports = { ignoreDuringBuilds: true }, env: { - NEXT_PUBLIC_GITHUB_URL: packageInfo.repository.url, + NEXT_PUBLIC_GITHUB_URL: process.env.GIT_URL ?? packageInfo.repository.url, NEXT_PUBLIC_APP_NAME: process.env.APP_NAME ?? packageInfo.displayName, NEXT_PUBLIC_DEFAULT_SERVER: process.env.DEFAULT_SERVER ?? "invidious.privacy.gd" diff --git a/src/components/MaterialColorPicker/ColorBox.tsx b/src/components/MaterialColorPicker/ColorBox.tsx new file mode 100644 index 0000000..6591dd3 --- /dev/null +++ b/src/components/MaterialColorPicker/ColorBox.tsx @@ -0,0 +1,20 @@ +import Box from "@mui/material/Box"; +import { styled } from "@mui/material/styles"; + +interface ColorBoxProps { + color: string; +} + +const ColorBox = styled(Box, { + shouldForwardProp: (prop) => prop !== "color" +})(({ theme, color }) => ({ + width: 24, + height: 24, + backgroundColor: color, + borderRadius: "50%", + borderColor: theme.palette.text.primary, + borderWidth: 2, + borderStyle: "solid" +})); + +export default ColorBox; diff --git a/src/components/MaterialColorPicker/index.tsx b/src/components/MaterialColorPicker/index.tsx new file mode 100644 index 0000000..c470e9a --- /dev/null +++ b/src/components/MaterialColorPicker/index.tsx @@ -0,0 +1,103 @@ +import { FC } from "react"; + +import Box from "@mui/material/Box"; +import Grid from "@mui/material/Grid"; +import Modal from "@mui/material/Modal"; +import Typography from "@mui/material/Typography"; +import { + blue, + green, + amber, + red, + cyan, + teal, + deepOrange, + indigo, + yellow, + lightBlue, + orange, + lime, + deepPurple, + lightGreen, + pink, + purple +} from "@mui/material/colors"; +import { useTheme } from "@mui/material/styles"; + +import ModalBox from "@components/ModalBox"; + +const colors = [ + red, + deepOrange, + orange, + amber, + yellow, + lime, + lightGreen, + green, + teal, + cyan, + lightBlue, + blue, + indigo, + deepPurple, + purple, + pink +]; + +const MaterialColorPicker: FC<{ + isOpen: boolean; + setState: (isOpen: boolean) => void; + selectedColor: string; + setColor: (color: string) => void; +}> = ({ setState, isOpen, selectedColor, setColor }) => { + const theme = useTheme(); + + return ( + setState(false)} + aria-labelledby="color-picker" + aria-describedby="Pick a material color" + component="div" + > + + + Pick a color + + + {colors.map((color, i) => ( + + {Object.values(color) + .slice(0, 10) + .map((shade, i) => ( + setColor(shade)} + key={i} + sx={{ + width: 24, + height: 24, + backgroundColor: shade, + borderRadius: "50%", + border: + shade == selectedColor + ? { + borderColor: theme.palette.text.primary, + borderWidth: 2, + borderStyle: "solid" + } + : null, + cursor: "pointer", + mb: 1 + }} + > + ))} + + ))} + + + + ); +}; + +export default MaterialColorPicker; diff --git a/src/components/ModalBox.ts b/src/components/ModalBox.ts new file mode 100644 index 0000000..3b113dd --- /dev/null +++ b/src/components/ModalBox.ts @@ -0,0 +1,17 @@ +import Box from "@mui/material/Box"; + +import styled from "@mui/system/styled"; + +const ModalBox = styled(Box)(({ theme }) => ({ + padding: "2rem", + position: "absolute", + left: "50%", + top: "50%", + transform: "translate(-50%, -50%)", + minWidth: "20rem", + backgroundColor: theme.palette.background.paper, + borderRadius: 5, + outline: "none" +})); + +export default ModalBox; diff --git a/src/components/Navbar/index.tsx b/src/components/Navbar/index.tsx index 5e649ad..f33ca65 100644 --- a/src/components/Navbar/index.tsx +++ b/src/components/Navbar/index.tsx @@ -95,19 +95,21 @@ const Navbar: FC = () => { - - - {process.env.NEXT_PUBLIC_APP_NAME} - + + + + {process.env.NEXT_PUBLIC_APP_NAME} + + void; + data: Stats; +}> = ({ modalIsOpen, setModalState, data }) => { + const [settings] = useSettings(); + + const lastUpdated = new Date(data.metadata.updatedAt * 1000); + + return ( + setModalState(false)} + aria-labelledby="stats-modal" + aria-describedby="Shows server stats" + > + + + Stats for {settings.invidiousServer} + + + Version: {data.version}

+ Software name: {data.software.name}
+ Software version: {data.software.version}
+ Software branch: {data.software.branch}

+ Is accepting registrations: {data.openRegistrations ? "Yes" : "No"} +

+ Total users: {data.usage.users.total}
+ Active in the past half year: {data.usage.users.activeHalfyear} +
+ Active in the past month: {data.usage.users.activeMonth}

+ Stats updated at: {lastUpdated.toLocaleDateString()} -{" "} + {lastUpdated.toLocaleTimeString()} +
+
+
+ ); +}; + +const Setting: FC<{ title: string; description?: string }> = ({ + title, + children, + description +}) => { + const theme = useTheme(); + + return ( + + + {title} + {description && ( + + {description} + + )} + + {children} + + ); +}; const Settings: NextPage = () => { const [settings, setSettings] = useSettings(); - const setSetting = (key: string, value?: string): void => { + const setSetting = (key: string, value?: string): void => setSettings({ ...settings, [key]: value }); - }; - - const [modalIsOpen, setModalState] = useState(false); const theme = useTheme(); + const [primaryColorModalIsOpen, setPrimaryColorModal] = useState(false); + const [accentColorModalIsOpen, setAccentColorModal] = useState(false); + + const [modalIsOpen, setModalState] = useState(false); + const instances = useQuery<[string, ServerInstance][]>( "invidiousInstances", () => @@ -65,103 +124,13 @@ const Settings: NextPage = () => { { retry: false } ); - const invidiousServerResponse = useQuery("invidiousInstance", () => - axios - .get(`https://${settings.invidiousServer}/api/v1/stats`) - .then((res) => res.data) + const invidiousServerResponse = useMutation( + "invidiousInstance", + (server) => + axios.get(`https://${server}/api/v1/stats`).then((res) => res.data) ); - const ColorSetting: FC<{ type: string }> = ({ type }) => { - const camelCase = toCamelCase(type) as "primaryColor" | "accentColor"; - - return ( - - - {type} - - {[ - blue[800], - red[800], - green[800], - cyan[800], - purple[800], - yellow[800], - orange[800] - ].map((color) => ( - setSetting(camelCase, color)} - key={color} - component="span" - sx={{ - width: 24, - height: 24, - backgroundColor: color, - borderRadius: "50%", - border: - color == settings[camelCase] - ? { - borderColor: theme.palette.text.primary, - borderWidth: 1, - borderStyle: "solid" - } - : null, - cursor: "pointer", - ml: 1.5 - }} - /> - ))} - - ); - }; - - const InfoModal: FC = () => { - const data = invidiousServerResponse.data!; - - const lastUpdated = new Date(data.metadata.updatedAt * 1000); - - return ( - setModalState(false)} - aria-labelledby="modal-modal-title" - aria-describedby="modal-modal-description" - > - - - Stats for {settings.invidiousServer} - - - Version: {data.version}

- Software name: {data.software.name}
- Software version: {data.software.version}
- Software branch: {data.software.branch}

- Is accepting registrations: {data.openRegistrations - ? "Yes" - : "No"}{" "} -

- Total users: {data.usage.users.total}
- Active in the past half year: {data.usage.users.activeHalfyear} -
- Active in the past month: {data.usage.users.activeMonth}
{" "} -
- Stats updated at: {lastUpdated.toLocaleDateString()} -{" "} - {lastUpdated.toLocaleTimeString()} -
-
-
- ); - }; + const allowsRegistrations = invidiousServerResponse.data?.openRegistrations; return ( <> @@ -179,10 +148,10 @@ const Settings: NextPage = () => { Theme - - - General theme - + { - - - + - + + + + setSetting("primaryColor", color)} + selectedColor={settings.primaryColor} + /> + + + + + + setSetting("accentColor", color)} + selectedColor={settings.accentColor} + /> + @@ -206,13 +203,28 @@ const Settings: NextPage = () => { - Miscellaneous + Data - - - Invidious Server - + + {!invidiousServerResponse.data && + !invidiousServerResponse.error && + !invidiousServerResponse.isLoading && ( + + invidiousServerResponse.mutate(settings.invidiousServer) + } + /> + )} {invidiousServerResponse.data && !invidiousServerResponse.isLoading && ( <> @@ -220,9 +232,14 @@ const Settings: NextPage = () => { onClick={() => setModalState(true)} sx={{ color: green[800], cursor: "pointer" }} /> - + )} + {invidiousServerResponse.error && ( )} @@ -238,6 +255,8 @@ const Settings: NextPage = () => { onChange={(e) => { const server = e.target.value; + invidiousServerResponse.mutate(server); + setSetting("invidiousServer", server); }} MenuProps={{ sx: { maxHeight: 300 } }} @@ -256,7 +275,89 @@ const Settings: NextPage = () => { ))} - + + + + + Location + + + + + {settings.storageType != StorageType.Local && ( + <> + {settings.storageType == "invidious" && allowsRegistrations && ( + + + + )} + + {settings.storageType == StorageType.RemoteServer && ( + + + + )} + + + + + + )} diff --git a/src/pages/trending.tsx b/src/pages/trending.tsx index af984fc..514acd2 100644 --- a/src/pages/trending.tsx +++ b/src/pages/trending.tsx @@ -109,7 +109,7 @@ export const getStaticProps: GetStaticProps = async ({}) => { ); return { - props: { trending } + props: { trending: trending.slice(0, 10) } }; }; diff --git a/src/utils/hooks.ts b/src/utils/hooks.ts index b1e4c15..d8e64f6 100644 --- a/src/utils/hooks.ts +++ b/src/utils/hooks.ts @@ -9,7 +9,8 @@ import Settings from "@interfaces/settings"; const defaultSettings: Settings = { primaryColor: red[800], accentColor: red[800], - invidiousServer: process.env.NEXT_PUBLIC_DEFAULT_SERVER as string + invidiousServer: process.env.NEXT_PUBLIC_DEFAULT_SERVER as string, + storageType: "local" }; export const useSettings = (): [