From be3c8dd6e651fa8ce3187c7e45b3509b403f8dee Mon Sep 17 00:00:00 2001 From: Sidney Alcantara Date: Mon, 9 May 2022 17:01:02 +1000 Subject: [PATCH] add SnackLogProvider --- src/Providers.tsx | 10 ++-- .../TableSettingsDialog.tsx | 19 ++++--- src/contexts/SnackLogContext.tsx | 49 +++++++++++++++++++ src/contexts/SwrContext.tsx | 24 +++++++++ 4 files changed, 89 insertions(+), 13 deletions(-) create mode 100644 src/contexts/SnackLogContext.tsx create mode 100644 src/contexts/SwrContext.tsx diff --git a/src/Providers.tsx b/src/Providers.tsx index 2093c1c5..03d64715 100644 --- a/src/Providers.tsx +++ b/src/Providers.tsx @@ -1,5 +1,6 @@ import { ErrorBoundary } from "react-error-boundary"; import ErrorFallback from "@src/components/ErrorFallback"; +import SwrProvider from "@src/contexts/SwrContext"; import { BrowserRouter } from "react-router-dom"; import { HelmetProvider } from "react-helmet-async"; import { Provider, Atom } from "jotai"; @@ -8,6 +9,7 @@ import createCache from "@emotion/cache"; import { CacheProvider } from "@emotion/react"; import RowyThemeProvider from "@src/theme/RowyThemeProvider"; import SnackbarProvider from "@src/contexts/SnackbarContext"; +import { SnackLogProvider } from "@src/contexts/SnackLogContext"; import { Suspense } from "react"; import Loading from "@src/components/Loading"; @@ -32,9 +34,11 @@ export default function Providers({ - }> - {children} - + + }> + {children} + + diff --git a/src/components/TableSettingsDialog/TableSettingsDialog.tsx b/src/components/TableSettingsDialog/TableSettingsDialog.tsx index 23996015..d0f6902b 100644 --- a/src/components/TableSettingsDialog/TableSettingsDialog.tsx +++ b/src/components/TableSettingsDialog/TableSettingsDialog.tsx @@ -1,9 +1,8 @@ import { useAtom, useSetAtom } from "jotai"; import useSWR from "swr"; import { useSnackbar } from "notistack"; -import { useLocation, useNavigate } from "react-router-dom"; +import { useNavigate } from "react-router-dom"; import { find, sortBy, get, isEmpty } from "lodash-es"; -import { FieldValues } from "react-hook-form"; import { Controller } from "react-hook-form"; import { DialogContentText, Stack, Typography } from "@mui/material"; @@ -31,8 +30,6 @@ import { import { TableSettings } from "@src/types/table"; import { analytics, logEvent } from "@src/analytics"; -// TODO: -// import { useSnackLogContext } from "@src/contexts/SnackLogContext"; import { runRoutes } from "@src/constants/runRoutes"; import { CONFIG, @@ -40,6 +37,7 @@ import { TABLE_SCHEMAS, } from "@src/config/dbPaths"; import { ROUTES } from "@src/constants/routes"; +import { useSnackLogContext } from "@src/contexts/SnackLogContext"; const customComponents = { tableName: { @@ -70,10 +68,9 @@ export default function TableSettingsDialog() { const [tables] = useAtom(tablesAtom, globalScope); const [rowyRun] = useAtom(rowyRunAtom, globalScope); - const location = useLocation(); const navigate = useNavigate(); const confirm = useSetAtom(confirmDialogAtom, globalScope); - // const snackLogContext = useSnackLogContext(); + const snackLogContext = useSnackLogContext(); const { enqueueSnackbar, closeSnackbar } = useSnackbar(); const sectionNames = Array.from( @@ -81,8 +78,11 @@ export default function TableSettingsDialog() { ); const { data: collections } = useSWR( - "firebaseCollections", - () => rowyRun({ route: runRoutes.listCollections }), + "collectionsList", + async () => { + const result = await rowyRun({ route: runRoutes.listCollections }); + return result || []; + }, { revalidateOnMount: true, revalidateOnFocus: false, @@ -130,8 +130,7 @@ export default function TableSettingsDialog() { if (hasExtensions) { // find derivative, default value - // TODO: - // snackLogContext.requestSnackLog(); + snackLogContext.requestSnackLog(); rowyRun({ route: runRoutes.buildFunction, body: { diff --git a/src/contexts/SnackLogContext.tsx b/src/contexts/SnackLogContext.tsx new file mode 100644 index 00000000..bd413cbb --- /dev/null +++ b/src/contexts/SnackLogContext.tsx @@ -0,0 +1,49 @@ +import { createContext, useContext, useState } from "react"; + +const DEFAULT_STATE = { + isSnackLogOpen: false, + latestBuildTimestamp: 0, +}; +const DEFAULT_FUNCTIONS = { + requestSnackLog: () => {}, + closeSnackLog: () => {}, +}; + +export const SnackLogContext = createContext({ + ...DEFAULT_STATE, + ...DEFAULT_FUNCTIONS, +}); +export const useSnackLogContext = () => useContext(SnackLogContext); + +export function SnackLogProvider({ children }: React.PropsWithChildren<{}>) { + const [state, setState] = useState(DEFAULT_STATE); + + const requestSnackLog: typeof DEFAULT_FUNCTIONS.requestSnackLog = () => { + setTimeout(() => { + setState({ + ...state, + latestBuildTimestamp: Date.now(), + isSnackLogOpen: true, + }); + }, 500); + }; + + const closeSnackLog: typeof DEFAULT_FUNCTIONS.closeSnackLog = () => + setState({ + ...state, + latestBuildTimestamp: 0, + isSnackLogOpen: false, + }); + + return ( + + {children} + + ); +} diff --git a/src/contexts/SwrContext.tsx b/src/contexts/SwrContext.tsx new file mode 100644 index 00000000..b3cf9b48 --- /dev/null +++ b/src/contexts/SwrContext.tsx @@ -0,0 +1,24 @@ +import { SWRConfig } from "swr"; + +// NOTE: This does not support React 18 yet. See: https://github.com/vercel/swr/issues/1904 + +// https://swr.vercel.app/docs/advanced/cache#localstorage-based-persistent-cache +function localStorageProvider() { + // When initializing, we restore the data from `localStorage` into a map. + const map = new Map(JSON.parse(localStorage.getItem("swr-cache") || "[]")); + + // Before unloading the app, we write back all the data into `localStorage`. + window.addEventListener("beforeunload", () => { + const appCache = JSON.stringify(Array.from(map.entries())); + localStorage.setItem("swr-cache", appCache); + }); + + // We still use the map for write & read for performance. + return map; +} + +export default function SwrProvider({ children }: React.PropsWithChildren<{}>) { + return ( + {children} + ); +}