From a5ce9113a936152d114604d9b6eba4ce493b84ce Mon Sep 17 00:00:00 2001 From: Brandon Fancher Date: Thu, 12 Dec 2024 16:36:16 +0000 Subject: [PATCH 1/8] Add accounts-related hooks. --- .../src/hooks/use-create-connection-token.ts | 33 +++++++++++++++++++ .../ui/src/hooks/use-current-accounts.ts | 22 +++++++++++++ .../ui/src/hooks/use-logged-in-user.ts | 25 ++++++++++++++ .../user/Chainmail/ui/src/hooks/use-logout.ts | 26 +++++++++++++++ .../ui/src/hooks/use-select-account.ts | 31 +++++++++++++++++ .../user/Chainmail/ui/src/lib/supervisor.ts | 1 + services/user/Chainmail/ui/src/lib/utils.ts | 17 ++++++++++ 7 files changed, 155 insertions(+) create mode 100644 services/user/Chainmail/ui/src/hooks/use-create-connection-token.ts create mode 100644 services/user/Chainmail/ui/src/hooks/use-current-accounts.ts create mode 100644 services/user/Chainmail/ui/src/hooks/use-logged-in-user.ts create mode 100644 services/user/Chainmail/ui/src/hooks/use-logout.ts create mode 100644 services/user/Chainmail/ui/src/hooks/use-select-account.ts diff --git a/services/user/Chainmail/ui/src/hooks/use-create-connection-token.ts b/services/user/Chainmail/ui/src/hooks/use-create-connection-token.ts new file mode 100644 index 000000000..e2b207cd1 --- /dev/null +++ b/services/user/Chainmail/ui/src/hooks/use-create-connection-token.ts @@ -0,0 +1,33 @@ +import { z } from "zod"; +import { useMutation } from "@tanstack/react-query"; +import { toast } from "sonner"; + +import { siblingUrl } from "@psibase/common-lib"; + +import { getSupervisor } from "@lib/supervisor"; +import { modifyUrlParams } from "@lib/utils"; + +export const useCreateConnectionToken = () => + useMutation({ + mutationFn: async () => { + const supervisor = await getSupervisor(); + const token = await supervisor.functionCall({ + method: "createConnectionToken", + params: [], + service: "accounts", + intf: "activeApp", + }); + return z.string().parse(token); + }, + onSuccess: (token) => { + window.location.href = modifyUrlParams( + siblingUrl(undefined, "accounts", null, false), + { + token, + }, + ); + }, + onError: (error) => { + toast.error(error.message); + }, + }); diff --git a/services/user/Chainmail/ui/src/hooks/use-current-accounts.ts b/services/user/Chainmail/ui/src/hooks/use-current-accounts.ts new file mode 100644 index 000000000..b0c8e3295 --- /dev/null +++ b/services/user/Chainmail/ui/src/hooks/use-current-accounts.ts @@ -0,0 +1,22 @@ +import { useQuery } from "@tanstack/react-query"; +import { z } from "zod"; + +import { getSupervisor } from "@lib/supervisor"; + +export const useCurrentAccounts = (enabled: boolean) => + useQuery({ + queryKey: ["currentAccounts"], + enabled, + initialData: [], + queryFn: async () => { + const supervisor = await getSupervisor(); + const connectedAccounts = await supervisor.functionCall({ + method: "getConnectedAccounts", + params: [], + service: "accounts", + intf: "activeApp", + }); + const res = z.string().array().parse(connectedAccounts); + return res; + }, + }); diff --git a/services/user/Chainmail/ui/src/hooks/use-logged-in-user.ts b/services/user/Chainmail/ui/src/hooks/use-logged-in-user.ts new file mode 100644 index 000000000..746620ae4 --- /dev/null +++ b/services/user/Chainmail/ui/src/hooks/use-logged-in-user.ts @@ -0,0 +1,25 @@ +import { useQuery } from "@tanstack/react-query"; +import { z } from "zod"; + +import { getSupervisor } from "@lib/supervisor"; + +export const useLoggedInUser = (enabled: boolean) => + useQuery({ + queryKey: ["loggedInUser"], + enabled, + initialData: null, + queryFn: async () => { + const supervisor = await getSupervisor(); + const res = await supervisor.functionCall({ + method: "getLoggedInUser", + params: [], + service: "accounts", + intf: "activeApp", + }); + if (res) { + return z.string().parse(res); + } else { + return null; + } + }, + }); diff --git a/services/user/Chainmail/ui/src/hooks/use-logout.ts b/services/user/Chainmail/ui/src/hooks/use-logout.ts new file mode 100644 index 000000000..c8241c9ef --- /dev/null +++ b/services/user/Chainmail/ui/src/hooks/use-logout.ts @@ -0,0 +1,26 @@ +import { useQueryClient, useMutation } from "@tanstack/react-query"; + +import { getSupervisor } from "@lib/supervisor"; + +export const useLogout = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationKey: ["logout"], + mutationFn: async () => { + const supervisor = await getSupervisor(); + return supervisor.functionCall({ + method: "logout", + params: [], + service: "accounts", + intf: "activeApp", + }); + }, + onSuccess: () => { + queryClient.refetchQueries({ queryKey: ["loggedInUser"] }); + setTimeout(() => { + queryClient.refetchQueries({ queryKey: ["loggedInUser"] }); + }, 2500); + }, + }); +}; diff --git a/services/user/Chainmail/ui/src/hooks/use-select-account.ts b/services/user/Chainmail/ui/src/hooks/use-select-account.ts new file mode 100644 index 000000000..b727e45cd --- /dev/null +++ b/services/user/Chainmail/ui/src/hooks/use-select-account.ts @@ -0,0 +1,31 @@ +import { useQueryClient, useMutation } from "@tanstack/react-query"; +import { toast } from "sonner"; +import { z } from "zod"; + +import { getSupervisor } from "@lib/supervisor"; + +export const useSelectAccount = () => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationKey: ["selectAccount"], + mutationFn: async (accountName: string) => { + const supervisor = await getSupervisor(); + void (await supervisor.functionCall({ + method: "login", + params: [z.string().parse(accountName)], + service: "accounts", + intf: "activeApp", + })); + }, + onSuccess: () => { + queryClient.refetchQueries({ queryKey: ["loggedInUser"] }); + setTimeout(() => { + queryClient.refetchQueries({ queryKey: ["loggedInUser"] }); + }, 2000); + }, + onError: (error) => { + toast.error(error.message); + }, + }); +}; diff --git a/services/user/Chainmail/ui/src/lib/supervisor.ts b/services/user/Chainmail/ui/src/lib/supervisor.ts index e2958d9f5..19c70e57c 100644 --- a/services/user/Chainmail/ui/src/lib/supervisor.ts +++ b/services/user/Chainmail/ui/src/lib/supervisor.ts @@ -4,5 +4,6 @@ const supervisor = new Supervisor(); export const getSupervisor = async () => { if (supervisor.isSupervisorInitialized) return supervisor; await supervisor.onLoaded(); + supervisor.preLoadPlugins([{ service: "accounts" }]); return supervisor; }; diff --git a/services/user/Chainmail/ui/src/lib/utils.ts b/services/user/Chainmail/ui/src/lib/utils.ts index 3c73df14b..76bf86b11 100644 --- a/services/user/Chainmail/ui/src/lib/utils.ts +++ b/services/user/Chainmail/ui/src/lib/utils.ts @@ -27,3 +27,20 @@ export function debounce any>( } export const wait = (ms: number) => new Promise((res) => setTimeout(res, ms)); + +export const modifyUrlParams = ( + url: string, + params: { [key: string]: string }, +): string => { + const urlObject = new URL(url); + + const parsObject = new URLSearchParams(urlObject.search); + + Object.entries(params).forEach(([key, value]) => { + parsObject.set(key, value); + }); + + urlObject.search = parsObject.toString(); + + return urlObject.toString(); +}; From b48993ec262054afc3cbcc0245a006c51ffed6d8 Mon Sep 17 00:00:00 2001 From: Brandon Fancher Date: Thu, 12 Dec 2024 16:36:34 +0000 Subject: [PATCH 2/8] Introduce and style account selection menu. --- .../ui/src/components/account-switcher.tsx | 163 ++++++++++++++---- 1 file changed, 133 insertions(+), 30 deletions(-) diff --git a/services/user/Chainmail/ui/src/components/account-switcher.tsx b/services/user/Chainmail/ui/src/components/account-switcher.tsx index 1e460dc4c..9d9b0a17a 100644 --- a/services/user/Chainmail/ui/src/components/account-switcher.tsx +++ b/services/user/Chainmail/ui/src/components/account-switcher.tsx @@ -1,5 +1,16 @@ import { useIncomingMessages, useUser } from "@hooks"; import { cn } from "@lib/utils"; +import { Avatar, AvatarFallback, AvatarImage } from "@shadcn/avatar"; +import { Button } from "@shadcn/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@shadcn/dropdown-menu"; import { Select, SelectContent, @@ -7,46 +18,138 @@ import { SelectTrigger, SelectValue, } from "@shadcn/select"; +import { + BadgeCheck, + Bell, + ChevronsUpDown, + CreditCard, + LogOut, + Sparkles, +} from "lucide-react"; interface AccountSwitcherProps { isCollapsed: boolean; } +const user = { + avatar: undefined, + name: "alice", +}; + export function AccountSwitcher({ isCollapsed }: AccountSwitcherProps) { const { setSelectedMessageId } = useIncomingMessages(); - const { availableAccounts, user, setUser } = useUser(); + // const { availableAccounts, user, setUser } = useUser(); return ( - + + + + + + + Upgrade to Pro + + + + + + + Account + + + + Billing + + + + Notifications + + + + + + Log out + + + ); + + // return ( + // + // ); } From c0bb32377c5d440a4ed1316684ba19213ab034d7 Mon Sep 17 00:00:00 2001 From: Brandon Fancher Date: Thu, 12 Dec 2024 19:45:37 +0000 Subject: [PATCH 3/8] Progress --- .../ui/src/components/account-switcher.tsx | 169 ++++++++++++------ services/user/Chainmail/ui/src/hooks/index.ts | 5 + .../ui/src/hooks/use-current-accounts.ts | 2 +- .../ui/src/hooks/use-logged-in-user.ts | 2 +- 4 files changed, 125 insertions(+), 53 deletions(-) diff --git a/services/user/Chainmail/ui/src/components/account-switcher.tsx b/services/user/Chainmail/ui/src/components/account-switcher.tsx index 9d9b0a17a..41286b30a 100644 --- a/services/user/Chainmail/ui/src/components/account-switcher.tsx +++ b/services/user/Chainmail/ui/src/components/account-switcher.tsx @@ -1,4 +1,11 @@ -import { useIncomingMessages, useUser } from "@hooks"; +import { + useCreateConnectionToken, + useCurrentAccounts, + useIncomingMessages, + useLoggedInUser, + useLogout, + useSelectAccount, +} from "@hooks"; import { cn } from "@lib/utils"; import { Avatar, AvatarFallback, AvatarImage } from "@shadcn/avatar"; import { Button } from "@shadcn/button"; @@ -8,23 +15,20 @@ import { DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, + DropdownMenuPortal, DropdownMenuSeparator, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, DropdownMenuTrigger, } from "@shadcn/dropdown-menu"; import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@shadcn/select"; -import { - BadgeCheck, - Bell, ChevronsUpDown, - CreditCard, + LogIn, LogOut, - Sparkles, + PlusCircle, + User, + UserPlus, } from "lucide-react"; interface AccountSwitcherProps { @@ -40,6 +44,19 @@ export function AccountSwitcher({ isCollapsed }: AccountSwitcherProps) { const { setSelectedMessageId } = useIncomingMessages(); // const { availableAccounts, user, setUser } = useUser(); + const { mutateAsync: onLogin } = useCreateConnectionToken(); + + const { data: loggedInUser } = useLoggedInUser(); + const isLoggedIn = !!loggedInUser; + + const { data: currentAccounts, isPending: isLoadingAccounts } = + useCurrentAccounts(); + + const isNoOptions = !isLoggedIn && currentAccounts.length == 0; + + const { mutateAsync: onLogout } = useLogout(); + const { mutateAsync: selectAccount } = useSelectAccount(); + return ( @@ -51,14 +68,18 @@ export function AccountSwitcher({ isCollapsed }: AccountSwitcherProps) { - {user.name[0]} + {loggedInUser ? ( + user.name[0] + ) : ( + + )} {isCollapsed ? null : ( <>
- {user.name} + {loggedInUser ? user.name : "Get started"}
@@ -73,47 +94,93 @@ export function AccountSwitcher({ isCollapsed }: AccountSwitcherProps) { align="end" sideOffset={4} > - -
- - - - {user.name[0]} - - -
- - {user.name} - -
-
-
- - - - - Upgrade to Pro + {loggedInUser ? ( + <> + +
+ + + + {user.name[0]} + + +
+ + {user.name} + +
+
+
+ + + ) : null} + {isNoOptions && ( + { + onLogin(); + }} + > + + + {isLoadingAccounts ? "Loading..." : "Login"} + -
- + )} - - - Account - - - - Billing - - - - Notifications - + {!isNoOptions ? ( + + + + + {loggedInUser || "Select an account"} + + + + + + Switch accounts + + {currentAccounts + .filter( + (account) => + account !== loggedInUser, + ) + .map((account) => ( + { + selectAccount(account); + }} + > + + {account} + + ))} + + { + onLogin(); + }} + > + + More... + + + + + ) : null} - - + { + onLogout(); + }} + > - Log out + Log out
diff --git a/services/user/Chainmail/ui/src/hooks/index.ts b/services/user/Chainmail/ui/src/hooks/index.ts index 9d9f80e91..9ddc642bf 100644 --- a/services/user/Chainmail/ui/src/hooks/index.ts +++ b/services/user/Chainmail/ui/src/hooks/index.ts @@ -1,3 +1,8 @@ +export * from "./use-create-connection-token"; +export * from "./use-current-accounts"; export * from "./use-local-storage"; +export * from "./use-logged-in-user"; +export * from "./use-logout"; export * from "./use-mail"; +export * from "./use-select-account"; export * from "./use-user"; diff --git a/services/user/Chainmail/ui/src/hooks/use-current-accounts.ts b/services/user/Chainmail/ui/src/hooks/use-current-accounts.ts index b0c8e3295..90a7c68a4 100644 --- a/services/user/Chainmail/ui/src/hooks/use-current-accounts.ts +++ b/services/user/Chainmail/ui/src/hooks/use-current-accounts.ts @@ -3,7 +3,7 @@ import { z } from "zod"; import { getSupervisor } from "@lib/supervisor"; -export const useCurrentAccounts = (enabled: boolean) => +export const useCurrentAccounts = (enabled = true) => useQuery({ queryKey: ["currentAccounts"], enabled, diff --git a/services/user/Chainmail/ui/src/hooks/use-logged-in-user.ts b/services/user/Chainmail/ui/src/hooks/use-logged-in-user.ts index 746620ae4..be3fb3f1a 100644 --- a/services/user/Chainmail/ui/src/hooks/use-logged-in-user.ts +++ b/services/user/Chainmail/ui/src/hooks/use-logged-in-user.ts @@ -3,7 +3,7 @@ import { z } from "zod"; import { getSupervisor } from "@lib/supervisor"; -export const useLoggedInUser = (enabled: boolean) => +export const useLoggedInUser = (enabled = true) => useQuery({ queryKey: ["loggedInUser"], enabled, From 213cc7c2118923c7f005fbebdeef80a8b2af002f Mon Sep 17 00:00:00 2001 From: Brandon Fancher Date: Thu, 12 Dec 2024 22:07:43 +0000 Subject: [PATCH 4/8] Progress --- .../user/Chainmail/ui/src/components/account-switcher.tsx | 8 ++++++-- .../Chainmail/ui/src/hooks/use-create-connection-token.ts | 2 +- services/user/Chainmail/ui/src/lib/supervisor.ts | 3 +-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/services/user/Chainmail/ui/src/components/account-switcher.tsx b/services/user/Chainmail/ui/src/components/account-switcher.tsx index 41286b30a..f317553bf 100644 --- a/services/user/Chainmail/ui/src/components/account-switcher.tsx +++ b/services/user/Chainmail/ui/src/components/account-switcher.tsx @@ -5,6 +5,7 @@ import { useLoggedInUser, useLogout, useSelectAccount, + useUser, } from "@hooks"; import { cn } from "@lib/utils"; import { Avatar, AvatarFallback, AvatarImage } from "@shadcn/avatar"; @@ -41,8 +42,11 @@ const user = { }; export function AccountSwitcher({ isCollapsed }: AccountSwitcherProps) { - const { setSelectedMessageId } = useIncomingMessages(); - // const { availableAccounts, user, setUser } = useUser(); + // const { setSelectedMessageId } = useIncomingMessages(); + // const { availableAccounts, user: userz, setUser } = useUser(); + + // console.log("******* availableAccounts:", availableAccounts); + // console.log("******* user:", userz); const { mutateAsync: onLogin } = useCreateConnectionToken(); diff --git a/services/user/Chainmail/ui/src/hooks/use-create-connection-token.ts b/services/user/Chainmail/ui/src/hooks/use-create-connection-token.ts index e2b207cd1..225078967 100644 --- a/services/user/Chainmail/ui/src/hooks/use-create-connection-token.ts +++ b/services/user/Chainmail/ui/src/hooks/use-create-connection-token.ts @@ -21,7 +21,7 @@ export const useCreateConnectionToken = () => }, onSuccess: (token) => { window.location.href = modifyUrlParams( - siblingUrl(undefined, "accounts", null, false), + siblingUrl(undefined, "accounts", null, true), { token, }, diff --git a/services/user/Chainmail/ui/src/lib/supervisor.ts b/services/user/Chainmail/ui/src/lib/supervisor.ts index 19c70e57c..05926899a 100644 --- a/services/user/Chainmail/ui/src/lib/supervisor.ts +++ b/services/user/Chainmail/ui/src/lib/supervisor.ts @@ -1,9 +1,8 @@ import { Supervisor } from "@psibase/common-lib"; const supervisor = new Supervisor(); + export const getSupervisor = async () => { - if (supervisor.isSupervisorInitialized) return supervisor; await supervisor.onLoaded(); - supervisor.preLoadPlugins([{ service: "accounts" }]); return supervisor; }; From d81462c308ecf8452c88c3d30ce2fc0ef04682c0 Mon Sep 17 00:00:00 2001 From: Brandon Fancher Date: Fri, 13 Dec 2024 23:28:56 +0000 Subject: [PATCH 5/8] Adjust menu and make it all work. --- .../ui/src/components/account-switcher.tsx | 128 ++++++------------ .../ui/src/components/compose-dialog.tsx | 4 +- services/user/Chainmail/ui/src/hooks/index.ts | 1 - .../user/Chainmail/ui/src/hooks/use-mail.ts | 20 +-- .../user/Chainmail/ui/src/hooks/use-user.ts | 65 --------- 5 files changed, 53 insertions(+), 165 deletions(-) delete mode 100644 services/user/Chainmail/ui/src/hooks/use-user.ts diff --git a/services/user/Chainmail/ui/src/components/account-switcher.tsx b/services/user/Chainmail/ui/src/components/account-switcher.tsx index f317553bf..8c2b371bb 100644 --- a/services/user/Chainmail/ui/src/components/account-switcher.tsx +++ b/services/user/Chainmail/ui/src/components/account-switcher.tsx @@ -1,14 +1,12 @@ import { useCreateConnectionToken, useCurrentAccounts, - useIncomingMessages, useLoggedInUser, useLogout, useSelectAccount, - useUser, } from "@hooks"; import { cn } from "@lib/utils"; -import { Avatar, AvatarFallback, AvatarImage } from "@shadcn/avatar"; +import { Avatar, AvatarFallback } from "@shadcn/avatar"; import { Button } from "@shadcn/button"; import { DropdownMenu, @@ -36,18 +34,7 @@ interface AccountSwitcherProps { isCollapsed: boolean; } -const user = { - avatar: undefined, - name: "alice", -}; - export function AccountSwitcher({ isCollapsed }: AccountSwitcherProps) { - // const { setSelectedMessageId } = useIncomingMessages(); - // const { availableAccounts, user: userz, setUser } = useUser(); - - // console.log("******* availableAccounts:", availableAccounts); - // console.log("******* user:", userz); - const { mutateAsync: onLogin } = useCreateConnectionToken(); const { data: loggedInUser } = useLoggedInUser(); @@ -61,6 +48,10 @@ export function AccountSwitcher({ isCollapsed }: AccountSwitcherProps) { const { mutateAsync: onLogout } = useLogout(); const { mutateAsync: selectAccount } = useSelectAccount(); + const otherConnectedAccounts = currentAccounts.filter( + (account) => account !== loggedInUser, + ); + return ( @@ -70,20 +61,15 @@ export function AccountSwitcher({ isCollapsed }: AccountSwitcherProps) { className={cn("w-full", !isCollapsed && "pl-1 pr-2")} > - - {loggedInUser ? ( - user.name[0] - ) : ( - - )} + {loggedInUser?.[0] ?? } {isCollapsed ? null : ( <>
- {loggedInUser ? user.name : "Get started"} + {loggedInUser ?? "Get started"}
@@ -103,17 +89,13 @@ export function AccountSwitcher({ isCollapsed }: AccountSwitcherProps) {
- - {user.name[0]} + {loggedInUser[0]}
- {user.name} + {loggedInUser}
@@ -129,41 +111,47 @@ export function AccountSwitcher({ isCollapsed }: AccountSwitcherProps) { > - {isLoadingAccounts ? "Loading..." : "Login"} + {isLoadingAccounts ? "Loading..." : "Log in"} )} - - {!isNoOptions ? ( + {!isNoOptions && !otherConnectedAccounts.length ? ( + { + onLogin(); + }} + > + + Switch account + + ) : null} + {!isNoOptions && otherConnectedAccounts.length ? ( + - {loggedInUser || "Select an account"} + {loggedInUser + ? "Switch account" + : "Select an account"} - - Switch accounts - - {currentAccounts - .filter( - (account) => - account !== loggedInUser, - ) - .map((account) => ( - { - selectAccount(account); - }} - > - - {account} - - ))} - + {otherConnectedAccounts.map((account) => ( + { + selectAccount(account); + }} + > + + {account} + + ))} + {otherConnectedAccounts.length ? ( + + ) : null} { onLogin(); @@ -175,8 +163,8 @@ export function AccountSwitcher({ isCollapsed }: AccountSwitcherProps) { - ) : null} - + + ) : null} { @@ -189,38 +177,4 @@ export function AccountSwitcher({ isCollapsed }: AccountSwitcherProps) {
); - - // return ( - // - // ); } diff --git a/services/user/Chainmail/ui/src/components/compose-dialog.tsx b/services/user/Chainmail/ui/src/components/compose-dialog.tsx index aea7bbf15..a8f26a8a5 100644 --- a/services/user/Chainmail/ui/src/components/compose-dialog.tsx +++ b/services/user/Chainmail/ui/src/components/compose-dialog.tsx @@ -27,7 +27,7 @@ import { Separator } from "@shadcn/separator"; import { MarkdownEditor } from "@components"; import { ControlBar } from "@components/editor"; -import { type Message, useDraftMessages, useUser } from "@hooks"; +import { type Message, useDraftMessages, useLoggedInUser } from "@hooks"; import { Form, @@ -58,7 +58,7 @@ export const ComposeDialog = ({ }) => { const [open, setOpen] = useState(false); const isSent = useRef(false); - const { user } = useUser(); + const { data: user } = useLoggedInUser(); const { drafts, setDrafts, getDrafts, deleteDraftById } = useDraftMessages(); diff --git a/services/user/Chainmail/ui/src/hooks/index.ts b/services/user/Chainmail/ui/src/hooks/index.ts index 9ddc642bf..54e1807a6 100644 --- a/services/user/Chainmail/ui/src/hooks/index.ts +++ b/services/user/Chainmail/ui/src/hooks/index.ts @@ -5,4 +5,3 @@ export * from "./use-logged-in-user"; export * from "./use-logout"; export * from "./use-mail"; export * from "./use-select-account"; -export * from "./use-user"; diff --git a/services/user/Chainmail/ui/src/hooks/use-mail.ts b/services/user/Chainmail/ui/src/hooks/use-mail.ts index d2812b915..922c524d2 100644 --- a/services/user/Chainmail/ui/src/hooks/use-mail.ts +++ b/services/user/Chainmail/ui/src/hooks/use-mail.ts @@ -1,6 +1,6 @@ import { atom, useAtom } from "jotai"; -import { useUser } from "./use-user"; +import { useLoggedInUser } from "./use-logged-in-user"; import { useQuery } from "@tanstack/react-query"; import { useLocalStorage } from "./use-local-storage"; import { getSupervisor } from "@lib/supervisor"; @@ -49,7 +49,7 @@ const transformRawMessagesToMessages = (rawMessages: RawMessage[]) => { ); }; -const getIncomingMessages = async (account: string | undefined) => { +const getIncomingMessages = async (account?: string | null) => { const supervisor = await getSupervisor(); // const res = await fetch(`/messages?receiver=${account}`); let rawMessages = (await supervisor.functionCall({ @@ -63,7 +63,7 @@ const getIncomingMessages = async (account: string | undefined) => { const incomingMsgAtom = atom(""); export function useIncomingMessages() { - const { user } = useUser(); + const { data: user } = useLoggedInUser(); const query = useQuery({ queryKey: ["incoming", user], queryFn: () => getIncomingMessages(user), @@ -82,7 +82,7 @@ export function useIncomingMessages() { }; } -const getArchivedMessages = async (account: string | undefined) => { +const getArchivedMessages = async (account?: string | null) => { const supervisor = await getSupervisor(); let rawMessages = (await supervisor.functionCall({ service: "chainmail", @@ -95,7 +95,7 @@ const getArchivedMessages = async (account: string | undefined) => { const archivedMsgAtom = atom(""); export function useArchivedMessages() { - const { user } = useUser(); + const { data: user } = useLoggedInUser(); const query = useQuery({ queryKey: ["archived", user, ""], queryFn: () => getArchivedMessages(user), @@ -114,7 +114,7 @@ export function useArchivedMessages() { }; } -const getSavedMessages = async (account: string | undefined) => { +const getSavedMessages = async (account?: string | null) => { const supervisor = await getSupervisor(); let rawMessages = (await supervisor.functionCall({ service: "chainmail", @@ -128,7 +128,7 @@ const getSavedMessages = async (account: string | undefined) => { const savedMsgAtom = atom(""); export function useSavedMessages() { - const { user } = useUser(); + const { data: user } = useLoggedInUser(); const query = useQuery({ queryKey: ["saved", user], queryFn: () => getSavedMessages(user), @@ -147,7 +147,7 @@ export function useSavedMessages() { }; } -const getSentMessages = async (account: string | undefined) => { +const getSentMessages = async (account?: string | null) => { const supervisor = await getSupervisor(); let rawMessages = (await supervisor.functionCall({ service: "chainmail", @@ -161,7 +161,7 @@ const getSentMessages = async (account: string | undefined) => { const sentMsgAtom = atom(""); export function useSentMessages() { - const { user } = useUser(); + const { data: user } = useLoggedInUser(); const query = useQuery({ queryKey: ["sent", user], queryFn: () => getSentMessages(user), @@ -182,7 +182,7 @@ export function useSentMessages() { const draftMsgAtom = atom(""); export function useDraftMessages() { - const { user } = useUser(); + const { data: user } = useLoggedInUser(); const [allDrafts, setDrafts, getDrafts] = useLocalStorage( "drafts", diff --git a/services/user/Chainmail/ui/src/hooks/use-user.ts b/services/user/Chainmail/ui/src/hooks/use-user.ts deleted file mode 100644 index a63bdaeda..000000000 --- a/services/user/Chainmail/ui/src/hooks/use-user.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { useEffect } from "react"; -import { atom, useAtom } from "jotai"; - -import { type PluginId } from "@psibase/common-lib"; - -import { getSupervisor } from "@lib/supervisor"; -interface SupervisorError { - code: number; - producer: PluginId; - message: string; -} - -const accountsAtom = atom([]); -const userAtom = atom(undefined); -export function useUser() { - const [availableAccounts, setAvailableAccounts] = useAtom(accountsAtom); - const [user, setUser] = useAtom(userAtom); - - const getConnectedAccounts = async () => { - const supervisor = await getSupervisor(); - try { - const res = (await supervisor.functionCall({ - service: "accounts", - intf: "activeApp", - method: "getConnectedAccounts", - params: [], - })) as string[]; - setAvailableAccounts(res); - } catch (e: unknown) { - console.error(`${(e as SupervisorError).message}`); - } - }; - - const logInAs = async (accountName: string) => { - const supervisor = await getSupervisor(); - try { - await supervisor.functionCall({ - service: "accounts", - intf: "activeApp", - method: "login", - params: [accountName], - }); - setUser(accountName); - } catch (e: unknown) { - console.error("ERROR setting user:"); - console.log(e); - } - }; - - useEffect(() => { - const logIn = async () => { - await logInAs("alice"); - await logInAs("bob"); - getConnectedAccounts(); - }; - if (availableAccounts.length) return; - logIn(); - }, []); - - return { - availableAccounts, - user, - setUser: logInAs, - }; -} From 197d8075f249cc13aeee5072c5efb8a74337b630 Mon Sep 17 00:00:00 2001 From: Brandon Fancher Date: Fri, 13 Dec 2024 23:36:37 +0000 Subject: [PATCH 6/8] Remove now-unnecessary getSupervisor. --- .../user/Chainmail/ui/src/components/compose-dialog.tsx | 5 ++--- .../user/Chainmail/ui/src/components/mail-display.tsx | 5 ++--- .../Chainmail/ui/src/hooks/use-create-connection-token.ts | 4 ++-- .../user/Chainmail/ui/src/hooks/use-current-accounts.ts | 3 +-- .../user/Chainmail/ui/src/hooks/use-logged-in-user.ts | 3 +-- services/user/Chainmail/ui/src/hooks/use-logout.ts | 3 +-- services/user/Chainmail/ui/src/hooks/use-mail.ts | 8 ++------ .../user/Chainmail/ui/src/hooks/use-select-account.ts | 3 +-- services/user/Chainmail/ui/src/lib/supervisor.ts | 8 -------- services/user/Chainmail/ui/src/main.tsx | 6 ++++-- services/user/Chainmail/ui/src/routes/index.ts | 1 + 11 files changed, 17 insertions(+), 32 deletions(-) delete mode 100644 services/user/Chainmail/ui/src/lib/supervisor.ts diff --git a/services/user/Chainmail/ui/src/components/compose-dialog.tsx b/services/user/Chainmail/ui/src/components/compose-dialog.tsx index a8f26a8a5..352f122af 100644 --- a/services/user/Chainmail/ui/src/components/compose-dialog.tsx +++ b/services/user/Chainmail/ui/src/components/compose-dialog.tsx @@ -10,8 +10,6 @@ import { toast } from "sonner"; import { type PluginId } from "@psibase/common-lib"; -import { getSupervisor } from "@lib/supervisor"; - import { Button } from "@shadcn/button"; import { Dialog, @@ -38,6 +36,8 @@ import { } from "@shadcn/form"; import { Input } from "@shadcn/input"; +import { supervisor } from "src/main"; + interface SupervisorError { code: number; producer: PluginId; @@ -122,7 +122,6 @@ export const ComposeDialog = ({ } try { - const supervisor = await getSupervisor(); // TODO: Improve error detection. This promise resolves with success before the transaction is pushed. await supervisor.functionCall({ service: "chainmail", diff --git a/services/user/Chainmail/ui/src/components/mail-display.tsx b/services/user/Chainmail/ui/src/components/mail-display.tsx index 14f7f5a34..8c9c5d3e7 100644 --- a/services/user/Chainmail/ui/src/components/mail-display.tsx +++ b/services/user/Chainmail/ui/src/components/mail-display.tsx @@ -24,9 +24,10 @@ import { ReplyDialogTriggerIconWithTooltip, } from "@components"; import { Message, useDraftMessages, useIncomingMessages } from "@hooks"; -import { getSupervisor } from "@lib/supervisor"; import { wait } from "@lib/utils"; +import { supervisor } from "src/main"; + export function MailDisplay({ message, mailbox, @@ -97,7 +98,6 @@ const ActionBar = ({ const onArchive = async (itemId: string) => { let id = parseInt(itemId); - const supervisor = await getSupervisor(); // TODO: Improve error detection. This promise resolves with success before the transaction is pushed. await supervisor.functionCall({ service: "chainmail", @@ -119,7 +119,6 @@ const ActionBar = ({ const onSave = async (itemId: string) => { let id = parseInt(itemId); - const supervisor = await getSupervisor(); await supervisor.functionCall({ service: "chainmail", intf: "api", diff --git a/services/user/Chainmail/ui/src/hooks/use-create-connection-token.ts b/services/user/Chainmail/ui/src/hooks/use-create-connection-token.ts index 225078967..9e2b1dbd0 100644 --- a/services/user/Chainmail/ui/src/hooks/use-create-connection-token.ts +++ b/services/user/Chainmail/ui/src/hooks/use-create-connection-token.ts @@ -4,13 +4,13 @@ import { toast } from "sonner"; import { siblingUrl } from "@psibase/common-lib"; -import { getSupervisor } from "@lib/supervisor"; import { modifyUrlParams } from "@lib/utils"; +import { supervisor } from "src/main"; + export const useCreateConnectionToken = () => useMutation({ mutationFn: async () => { - const supervisor = await getSupervisor(); const token = await supervisor.functionCall({ method: "createConnectionToken", params: [], diff --git a/services/user/Chainmail/ui/src/hooks/use-current-accounts.ts b/services/user/Chainmail/ui/src/hooks/use-current-accounts.ts index 90a7c68a4..475efde14 100644 --- a/services/user/Chainmail/ui/src/hooks/use-current-accounts.ts +++ b/services/user/Chainmail/ui/src/hooks/use-current-accounts.ts @@ -1,7 +1,7 @@ import { useQuery } from "@tanstack/react-query"; import { z } from "zod"; -import { getSupervisor } from "@lib/supervisor"; +import { supervisor } from "src/main"; export const useCurrentAccounts = (enabled = true) => useQuery({ @@ -9,7 +9,6 @@ export const useCurrentAccounts = (enabled = true) => enabled, initialData: [], queryFn: async () => { - const supervisor = await getSupervisor(); const connectedAccounts = await supervisor.functionCall({ method: "getConnectedAccounts", params: [], diff --git a/services/user/Chainmail/ui/src/hooks/use-logged-in-user.ts b/services/user/Chainmail/ui/src/hooks/use-logged-in-user.ts index be3fb3f1a..b804853df 100644 --- a/services/user/Chainmail/ui/src/hooks/use-logged-in-user.ts +++ b/services/user/Chainmail/ui/src/hooks/use-logged-in-user.ts @@ -1,7 +1,7 @@ import { useQuery } from "@tanstack/react-query"; import { z } from "zod"; -import { getSupervisor } from "@lib/supervisor"; +import { supervisor } from "src/main"; export const useLoggedInUser = (enabled = true) => useQuery({ @@ -9,7 +9,6 @@ export const useLoggedInUser = (enabled = true) => enabled, initialData: null, queryFn: async () => { - const supervisor = await getSupervisor(); const res = await supervisor.functionCall({ method: "getLoggedInUser", params: [], diff --git a/services/user/Chainmail/ui/src/hooks/use-logout.ts b/services/user/Chainmail/ui/src/hooks/use-logout.ts index c8241c9ef..7ef1b1818 100644 --- a/services/user/Chainmail/ui/src/hooks/use-logout.ts +++ b/services/user/Chainmail/ui/src/hooks/use-logout.ts @@ -1,6 +1,6 @@ import { useQueryClient, useMutation } from "@tanstack/react-query"; -import { getSupervisor } from "@lib/supervisor"; +import { supervisor } from "src/main"; export const useLogout = () => { const queryClient = useQueryClient(); @@ -8,7 +8,6 @@ export const useLogout = () => { return useMutation({ mutationKey: ["logout"], mutationFn: async () => { - const supervisor = await getSupervisor(); return supervisor.functionCall({ method: "logout", params: [], diff --git a/services/user/Chainmail/ui/src/hooks/use-mail.ts b/services/user/Chainmail/ui/src/hooks/use-mail.ts index 922c524d2..b9d8ac653 100644 --- a/services/user/Chainmail/ui/src/hooks/use-mail.ts +++ b/services/user/Chainmail/ui/src/hooks/use-mail.ts @@ -3,7 +3,8 @@ import { atom, useAtom } from "jotai"; import { useLoggedInUser } from "./use-logged-in-user"; import { useQuery } from "@tanstack/react-query"; import { useLocalStorage } from "./use-local-storage"; -import { getSupervisor } from "@lib/supervisor"; + +import { supervisor } from "src/main"; const composeAtom = atom(false); export function useCompose() { @@ -50,8 +51,6 @@ const transformRawMessagesToMessages = (rawMessages: RawMessage[]) => { }; const getIncomingMessages = async (account?: string | null) => { - const supervisor = await getSupervisor(); - // const res = await fetch(`/messages?receiver=${account}`); let rawMessages = (await supervisor.functionCall({ service: "chainmail", intf: "queries", @@ -83,7 +82,6 @@ export function useIncomingMessages() { } const getArchivedMessages = async (account?: string | null) => { - const supervisor = await getSupervisor(); let rawMessages = (await supervisor.functionCall({ service: "chainmail", intf: "queries", @@ -115,7 +113,6 @@ export function useArchivedMessages() { } const getSavedMessages = async (account?: string | null) => { - const supervisor = await getSupervisor(); let rawMessages = (await supervisor.functionCall({ service: "chainmail", intf: "queries", @@ -148,7 +145,6 @@ export function useSavedMessages() { } const getSentMessages = async (account?: string | null) => { - const supervisor = await getSupervisor(); let rawMessages = (await supervisor.functionCall({ service: "chainmail", intf: "queries", diff --git a/services/user/Chainmail/ui/src/hooks/use-select-account.ts b/services/user/Chainmail/ui/src/hooks/use-select-account.ts index b727e45cd..f1e9f9dba 100644 --- a/services/user/Chainmail/ui/src/hooks/use-select-account.ts +++ b/services/user/Chainmail/ui/src/hooks/use-select-account.ts @@ -2,7 +2,7 @@ import { useQueryClient, useMutation } from "@tanstack/react-query"; import { toast } from "sonner"; import { z } from "zod"; -import { getSupervisor } from "@lib/supervisor"; +import { supervisor } from "src/main"; export const useSelectAccount = () => { const queryClient = useQueryClient(); @@ -10,7 +10,6 @@ export const useSelectAccount = () => { return useMutation({ mutationKey: ["selectAccount"], mutationFn: async (accountName: string) => { - const supervisor = await getSupervisor(); void (await supervisor.functionCall({ method: "login", params: [z.string().parse(accountName)], diff --git a/services/user/Chainmail/ui/src/lib/supervisor.ts b/services/user/Chainmail/ui/src/lib/supervisor.ts deleted file mode 100644 index 05926899a..000000000 --- a/services/user/Chainmail/ui/src/lib/supervisor.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Supervisor } from "@psibase/common-lib"; - -const supervisor = new Supervisor(); - -export const getSupervisor = async () => { - await supervisor.onLoaded(); - return supervisor; -}; diff --git a/services/user/Chainmail/ui/src/main.tsx b/services/user/Chainmail/ui/src/main.tsx index 8130a22e6..16a904fb4 100644 --- a/services/user/Chainmail/ui/src/main.tsx +++ b/services/user/Chainmail/ui/src/main.tsx @@ -5,14 +5,16 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { MilkdownProvider } from "@milkdown/react"; import { ProsemirrorAdapterProvider } from "@prosemirror-adapter/react"; -import { Drafts, Editor, Home, Sent, Saved, Viewer } from "@routes"; +import { Archived, Drafts, Editor, Home, Sent, Saved, Viewer } from "@routes"; import { TooltipProvider } from "@shadcn/tooltip"; +import { Supervisor } from "@psibase/common-lib"; + import DefaultLayout from "./layouts/default"; import "./styles/globals.css"; -import Archived from "@routes/archived"; +export const supervisor = new Supervisor(); const queryClient = new QueryClient(); const router = createBrowserRouter([ diff --git a/services/user/Chainmail/ui/src/routes/index.ts b/services/user/Chainmail/ui/src/routes/index.ts index caee0518d..38b67de3d 100644 --- a/services/user/Chainmail/ui/src/routes/index.ts +++ b/services/user/Chainmail/ui/src/routes/index.ts @@ -1,3 +1,4 @@ +export * from "./archived"; export * from "./drafts"; export * from "./editor"; export * from "./home"; From df4407885cabbc5f2ae1626690ca70dc6b2028a3 Mon Sep 17 00:00:00 2001 From: Brandon Fancher Date: Fri, 13 Dec 2024 23:53:35 +0000 Subject: [PATCH 7/8] Disable nav items when user logged out. --- .../Chainmail/ui/src/components/mode-toggle.tsx | 2 +- .../Chainmail/ui/src/components/nav-menu.tsx | 12 +++++++++--- .../user/Chainmail/ui/src/components/nav.tsx | 4 ++++ services/user/Chainmail/ui/src/routes/home.tsx | 16 +++++++++++----- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/services/user/Chainmail/ui/src/components/mode-toggle.tsx b/services/user/Chainmail/ui/src/components/mode-toggle.tsx index 7127b113e..9d2e8ae3f 100644 --- a/services/user/Chainmail/ui/src/components/mode-toggle.tsx +++ b/services/user/Chainmail/ui/src/components/mode-toggle.tsx @@ -15,7 +15,7 @@ export function ModeToggle() { return ( -