From dc3fe6adb60956c94cb29da83272c7d0e0b93218 Mon Sep 17 00:00:00 2001 From: Derrick Hammer Date: Mon, 16 Oct 2023 14:55:01 -0400 Subject: [PATCH] refactor: split Lume Provider into LumeStatusProvider, NetworksProvider, and AuthProvider --- src/components/AuthProvider.tsx | 38 ++++++++++ src/components/LumeStatusProvider.tsx | 45 ++++++++++++ .../LumeProvider.tsx => NetworksProvider.tsx} | 69 ++++++------------- .../lume/LumeDashboard/LumeDashboard.tsx | 6 +- .../lume/LumeIdentity/LumeIdentityContext.ts | 6 +- .../lume/LumeIdentity/components.tsx | 12 ++-- src/index.ts | 18 +++-- stories/LumeDashboard.stories.tsx | 6 +- stories/LumeIdentity.stories.tsx | 6 +- 9 files changed, 137 insertions(+), 69 deletions(-) create mode 100644 src/components/AuthProvider.tsx create mode 100644 src/components/LumeStatusProvider.tsx rename src/components/{lume/LumeProvider.tsx => NetworksProvider.tsx} (66%) diff --git a/src/components/AuthProvider.tsx b/src/components/AuthProvider.tsx new file mode 100644 index 0000000..7d050fa --- /dev/null +++ b/src/components/AuthProvider.tsx @@ -0,0 +1,38 @@ +import { createContext, useState, useContext, ReactNode } from "react"; + +// AuthContextType +export interface AuthContextType { + isLoggedIn: boolean; + setIsLoggedIn: (value: boolean) => void; +} + +// AuthContext +const AuthContext = createContext(undefined); + +// AuthProvider +interface AuthProviderProps { + children: ReactNode; +} + +export const AuthProvider: React.FC = ({ children }) => { + const [isLoggedIn, setIsLoggedIn] = useState(false); + + return ( + + {children} + + ); +}; + +// useAuth hook +export function useAuth() { + const context = useContext(AuthContext); + + if (!context) { + throw new Error("useAuth must be used within an AuthProvider"); + } + + return context; +} + +export default AuthProvider; diff --git a/src/components/LumeStatusProvider.tsx b/src/components/LumeStatusProvider.tsx new file mode 100644 index 0000000..1a80dc6 --- /dev/null +++ b/src/components/LumeStatusProvider.tsx @@ -0,0 +1,45 @@ +import { createContext, useState, useContext, ReactNode } from "react"; + +// LumeStatusContextType +interface LumeStatusContextType { + inited: boolean; + setInited: (value: boolean) => void; + ready: boolean; + setReady: (value: boolean) => void; +} + +// LumeStatusContext +export const LumeStatusContext = createContext< + LumeStatusContextType | undefined +>(undefined); + +// LumeStatusProvider +interface LumeStatusProviderProps { + children: ReactNode; +} + +export const LumeStatusProvider: React.FC = ({ + children, +}) => { + const [inited, setInited] = useState(false); + const [ready, setReady] = useState(false); + + return ( + + {children} + + ); +}; + +// useLumeStatus hook +export function useLumeStatus() { + const context = useContext(LumeStatusContext); + + if (!context) { + throw new Error("useLumeStatus must be used within a LumeStatusProvider"); + } + + return context; +} + +export default LumeStatusProvider; diff --git a/src/components/lume/LumeProvider.tsx b/src/components/NetworksProvider.tsx similarity index 66% rename from src/components/lume/LumeProvider.tsx rename to src/components/NetworksProvider.tsx index 715bc0e..4f3888c 100644 --- a/src/components/lume/LumeProvider.tsx +++ b/src/components/NetworksProvider.tsx @@ -8,7 +8,6 @@ import { } from "react"; import { createClient as createNetworkRegistryClient } from "@lumeweb/kernel-network-registry-client"; import { createNetworkClient } from "@lumeweb/libkernel/module"; -import { init, loginComplete } from "@lumeweb/libkernel/kernel"; type SyncState = "done" | "syncing" | "error"; @@ -26,45 +25,35 @@ interface NetworkStatus { error?: string; } -type LumeObject = { +export interface NetworksContextType { networks: Network[]; -}; - -export type LumeContextType = { - isLoggedIn: boolean; - setIsLoggedIn: (value: boolean) => void; - lume: LumeObject; - inited: boolean; - setInited: React.Dispatch>; - ready: boolean; - setReady: React.Dispatch>; -}; + setNetworks: React.Dispatch>; +} const networkRegistry = createNetworkRegistryClient(); -const LumeContext = createContext(undefined); +// Networks Context +const NetworksContext = createContext( + undefined, +); -const LumeProvider = ({ children }) => { - const [isLoggedIn, setIsLoggedIn] = useState(false); - const [ready, setReady] = useState(false); - const [inited, setInited] = useState(false); - const [lume, setLume] = useState({ networks: [] }); +const NetworksProvider = ({ children }) => { + const [networks, setNetworks] = useState([]); const statusUnsubs = useRef(new Map()); const isMounted = useRef(true); // Use a ref to track mounting const handleStatusUpdate = useCallback((id, newNetwork) => { - setLume((prevLume) => { - const updatedNetworks = prevLume.networks.map((network) => + setNetworks((prevNetworks) => { + return prevNetworks.map((network) => network.id === id ? { ...network, ...newNetwork } : network, ); - return { ...prevLume, networks: updatedNetworks }; }); }, []); const fetchAndUpdateNetworks = useCallback(async () => { const unsub = () => { statusUnsubs.current.forEach((unsub) => unsub()); - statusUnsubs.current = new Map(); + statusUnsubs.current.clear(); }; try { @@ -110,10 +99,7 @@ const LumeProvider = ({ children }) => { statusUnsubs.current = newStatusUnsubs; if (isMounted.current) { - setLume((prevLume) => ({ - ...prevLume, - networks: Array.from(newNetworksMap.values()), - })); + setNetworks(Array.from(newNetworksMap.values())); } else { unsub(); } @@ -139,29 +125,18 @@ const LumeProvider = ({ children }) => { }, [fetchAndUpdateNetworks]); return ( - + {children} - + ); }; -export default LumeProvider; - -export function useLume() { - const ctx = useContext(LumeContext); - - if (!ctx) { - throw new Error("useLume must be used within a LumeProvider"); +export function useNetworks() { + const context = useContext(NetworksContext); + if (!context) { + throw new Error("useNetworks must be used within a NetworksProvider"); } - - return ctx; + return context; } + +export default NetworksProvider; diff --git a/src/components/lume/LumeDashboard/LumeDashboard.tsx b/src/components/lume/LumeDashboard/LumeDashboard.tsx index 58fc292..b8be719 100644 --- a/src/components/lume/LumeDashboard/LumeDashboard.tsx +++ b/src/components/lume/LumeDashboard/LumeDashboard.tsx @@ -1,11 +1,11 @@ import * as Dialog from "@radix-ui/react-dialog"; -import { Network, useLume } from "../LumeProvider"; import Logo from "../../../assets/lume-logo.png"; import { cva } from "class-variance-authority"; import { cn } from "../../utils"; import { useState, useEffect } from "react"; import React from "react"; import camelCase from "camelcase"; +import { useNetworks, type Network } from "../../NetworksProvider"; const SYNCSTATE_TO_TEXT: Record = { done: "Synced", @@ -18,9 +18,7 @@ LumeDashboardTrigger.displayName = "LumeDashboardTrigger"; const LumeDashboard = (props: any) => { const { children }: { children: React.PropsWithChildren } = props; - const { - lume: { networks }, - } = useLume(); + const { networks } = useNetworks(); const [uniqueNetworkTypes, setUniqueNetworkTypes] = useState([]); diff --git a/src/components/lume/LumeIdentity/LumeIdentityContext.ts b/src/components/lume/LumeIdentity/LumeIdentityContext.ts index 7c595c3..34ae2c3 100644 --- a/src/components/lume/LumeIdentity/LumeIdentityContext.ts +++ b/src/components/lume/LumeIdentity/LumeIdentityContext.ts @@ -3,15 +3,15 @@ import { // loginComplete, // logoutComplete, } from "@lumeweb/libkernel/kernel"; -import { useLume } from "../LumeProvider"; import React, { useContext } from "react"; +import { useAuth } from "../../AuthProvider.js"; export const LumeIdentityContext = React.createContext< { open: boolean; setOpen: (open: boolean) => void } | undefined >(undefined); -export function useLumeIndentity() { - const { isLoggedIn, setIsLoggedIn } = useLume(); +export function useLumeIdentity() { + const { isLoggedIn, setIsLoggedIn } = useAuth(); const ctx = useContext(LumeIdentityContext); if (!ctx) { diff --git a/src/components/lume/LumeIdentity/components.tsx b/src/components/lume/LumeIdentity/components.tsx index 3524f3f..0b38aad 100644 --- a/src/components/lume/LumeIdentity/components.tsx +++ b/src/components/lume/LumeIdentity/components.tsx @@ -10,7 +10,7 @@ import { ExclamationTriangleIcon, } from "@radix-ui/react-icons"; import { AnimatePresence, m } from "framer-motion"; -import { useLumeIndentity } from "./LumeIdentityContext"; +import { useLumeIdentity } from "./LumeIdentityContext"; import { useMemo, useState } from "react"; import * as bip39 from "@scure/bip39"; @@ -54,7 +54,7 @@ const SubmitButtonComponent = () => { }; const SeedPhraseInputComponent = () => { - const { signIn } = useLumeIndentity(); + const { signIn } = useLumeIdentity(); return ( { "idle" | "clicked" >("idle"); const [step, setStep] = useState(0); - const { signIn } = useLumeIndentity(); + const { signIn } = useLumeIdentity(); const phrases = useMemo(() => { return bip39 @@ -158,10 +158,12 @@ const SeedPhraseGenerationComponent = ({ phraseLength = 12 }) => {
- + {phrase} - + {index + 1}
diff --git a/src/index.ts b/src/index.ts index ae53bb9..1fcdb98 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,18 @@ export { - default as LumeProvider, - useLume, - type LumeContextType, -} from "./components/lume/LumeProvider"; + default as AuthProvider, + useAuth, + type AuthContextType, +} from "./components/AuthProvider"; +export { + default as NetworksProvider, + useNetworks, + type NetworksContextType, +} from "./components/NetworksProvider"; +export { + default as LumeStatusProvider, + useLumeStatus, + type LumeStatusContext, +} from "src/components/LumeStatusProvider.js"; export { default as LumeDashboard, LumeDashboardTrigger, diff --git a/stories/LumeDashboard.stories.tsx b/stories/LumeDashboard.stories.tsx index 084852b..6957aad 100644 --- a/stories/LumeDashboard.stories.tsx +++ b/stories/LumeDashboard.stories.tsx @@ -1,7 +1,7 @@ import React from "react"; import { StoryFn, Meta } from "@storybook/react"; import LumeDashboard from "../src/components/lume/LumeDashboard/LumeDashboard.js"; -import LumeProvider from "../src/components/lume/LumeProvider.js"; +import NetworksProvider from "src/components/NetworksProvider.js"; export default { title: "LumeDashboard", @@ -9,9 +9,9 @@ export default { } as Meta; const Template: StoryFn = (args) => ( - + - + ); export const Primary = Template.bind({}); diff --git a/stories/LumeIdentity.stories.tsx b/stories/LumeIdentity.stories.tsx index 873fadd..310c558 100644 --- a/stories/LumeIdentity.stories.tsx +++ b/stories/LumeIdentity.stories.tsx @@ -1,7 +1,7 @@ import React from "react"; import { StoryFn, Meta } from "@storybook/react"; import LumeIdentity from "../src/components/lume/LumeIdentity/LumeIdentity.js"; -import LumeProvider from "../src/components/lume/LumeProvider.js"; +import AuthProvider from "src/components/AuthProvider.js"; export default { title: "LumeIdentity", @@ -9,9 +9,9 @@ export default { } as Meta; const Template: StoryFn = (args) => ( - + - + ); export const Primary = Template.bind({});