From ac553ab01b6d7285541f67160ffdb52bb3cca1db Mon Sep 17 00:00:00 2001 From: greenflame089 Date: Tue, 5 Aug 2025 00:59:08 -0400 Subject: [PATCH] Add multiple name support --- src/components/layout/Navbar/Navbar.tsx | 21 ++++++++++++- src/pages/Mail/AliasMail.tsx | 3 +- src/pages/Mail/Mail.tsx | 9 ++++-- src/pages/Mail/SentMail.tsx | 10 +++++-- src/state/features/authSlice.ts | 18 +++++++---- src/state/features/mailSlice.ts | 7 ++++- src/utils/qortalRequestFunctions.ts | 29 ++++++++++++++++++ src/wrappers/GlobalWrapper.tsx | 40 +++++++++++++++---------- 8 files changed, 109 insertions(+), 28 deletions(-) create mode 100644 src/utils/qortalRequestFunctions.ts diff --git a/src/components/layout/Navbar/Navbar.tsx b/src/components/layout/Navbar/Navbar.tsx index 6148cea..b97d4cd 100644 --- a/src/components/layout/Navbar/Navbar.tsx +++ b/src/components/layout/Navbar/Navbar.tsx @@ -33,13 +33,17 @@ interface Props { userName: string | null userAvatar: string authenticate: () => void + accountNames: { name: string }[] + setActiveName: (name: string) => void } const NavBar: React.FC = ({ isAuthenticated, userName, userAvatar, - authenticate + authenticate, + accountNames, + setActiveName }) => { const navigate = useNavigate() const dispatch = useDispatch() @@ -134,6 +138,21 @@ const NavBar: React.FC = ({ horizontal: 'left' }} > + {accountNames + .filter(n => n.name) + .map(n => ( + { + setActiveName(n.name) + handleClose() + }} + > + + {n.name === userName ? "✔︎ " : ""}{n.name} + + + ))} { setIsOpenModal(true) diff --git a/src/pages/Mail/AliasMail.tsx b/src/pages/Mail/AliasMail.tsx index 965c5c3..1200db2 100644 --- a/src/pages/Mail/AliasMail.tsx +++ b/src/pages/Mail/AliasMail.tsx @@ -19,7 +19,7 @@ import Tabs from '@mui/material/Tabs' import Tab from '@mui/material/Tab' import { useFetchMail } from '../../hooks/useFetchMail' import { ShowMessage } from './ShowMessage' -import { addToHashMapMail } from '../../state/features/mailSlice' +import { addToHashMapMail, clearMessages } from '../../state/features/mailSlice' import { setIsLoadingGlobal, setUserAvatarHash @@ -269,6 +269,7 @@ export const AliasMail = ({ value, onOpen, messageOpenedId}: AliasMailProps) => const firstMount = useRef(null) useEffect(() => { if (user?.name && (!firstMount.current || firstMount.current !== value)) { + dispatch(clearMessages()); setMailMessages([]) setTimeout(() => { getMessages() diff --git a/src/pages/Mail/Mail.tsx b/src/pages/Mail/Mail.tsx index 53dad24..1a905e8 100644 --- a/src/pages/Mail/Mail.tsx +++ b/src/pages/Mail/Mail.tsx @@ -46,6 +46,7 @@ import Tabs from "@mui/material/Tabs"; import Tab from "@mui/material/Tab"; import { useFetchMail } from "../../hooks/useFetchMail"; import { ShowMessage } from "./ShowMessage"; +import { clearMessages } from '../../state/features/mailSlice' import SimpleTable from "./MailTable"; import { AliasMail } from "./AliasMail"; @@ -364,12 +365,16 @@ export const Mail = ({ isFromTo }: MailProps) => { }; const firstMount = useRef(false); + const prevName = useRef(); useEffect(() => { - if (user?.name && !firstMount.current) { + if (!user?.name) return; + if (!firstMount.current || prevName.current !== user.name) { + dispatch(clearMessages()); getMessages(true); firstMount.current = true; } - }, [user]); + prevName.current = user.name; + }, [user?.name]); function a11yProps(index: number) { return { diff --git a/src/pages/Mail/SentMail.tsx b/src/pages/Mail/SentMail.tsx index 37159d0..6476099 100644 --- a/src/pages/Mail/SentMail.tsx +++ b/src/pages/Mail/SentMail.tsx @@ -19,7 +19,7 @@ import Tabs from '@mui/material/Tabs' import Tab from '@mui/material/Tab' import { useFetchMail } from '../../hooks/useFetchMail' import { ShowMessage } from './ShowMessage' -import { addToHashMapMail } from '../../state/features/mailSlice' +import { addToHashMapMail, clearMessages } from '../../state/features/mailSlice' import { setIsLoadingGlobal, setUserAvatarHash @@ -223,12 +223,16 @@ export const SentMail = ({onOpen}: SentMailProps) => { }, [getMailMessages, user]) const firstMount = useRef(false); + const prevName = useRef(); useEffect(() => { - if (user?.name && !firstMount.current) { + if (!user?.name) return; + if (!firstMount.current || prevName.current !== user.name) { + dispatch(clearMessages()); getMessages(true); firstMount.current = true; } - }, [user]); + prevName.current = user.name; + }, [user?.name]); const interval = useRef(null) diff --git a/src/state/features/authSlice.ts b/src/state/features/authSlice.ts index cd73e3a..5aeb378 100644 --- a/src/state/features/authSlice.ts +++ b/src/state/features/authSlice.ts @@ -1,13 +1,21 @@ import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'; +export interface NameRecord { + name: string; + owner: string; +} + +interface User { + address: string; + publicKey: string; + name?: string; + names?: NameRecord[]; +} interface AuthState { - user: { - address: string; - publicKey: string; - name?: string; - } | null; + user: User | null; } + const initialState: AuthState = { user: null }; diff --git a/src/state/features/mailSlice.ts b/src/state/features/mailSlice.ts index 7680688..b49f053 100644 --- a/src/state/features/mailSlice.ts +++ b/src/state/features/mailSlice.ts @@ -202,6 +202,10 @@ export const mailSlice = createSlice({ const subject = action.payload state.hashMapSavedSubjects[subject.id] = subject }, + clearMessages: (state) => { + state.mailMessages = []; + state.hashMapMailMessages = {}; + }, updateInHashMap: (state, action) => { const { id } = action.payload const post = action.payload @@ -359,7 +363,8 @@ export const { addToHashMapMail, upsertMessagesBeginning, addAllHashMapSubject, - addToHashMapSubject + addToHashMapSubject, + clearMessages } = mailSlice.actions export default mailSlice.reducer diff --git a/src/utils/qortalRequestFunctions.ts b/src/utils/qortalRequestFunctions.ts new file mode 100644 index 0000000..d4dc232 --- /dev/null +++ b/src/utils/qortalRequestFunctions.ts @@ -0,0 +1,29 @@ +export interface NameRecord { + name: string; + owner: string; +} + +export async function getAccountNames(address: string): Promise { + try { + const list = await qortalRequest({ + action: 'GET_ACCOUNT_NAMES', + address, + }); + if (Array.isArray(list) && list.length) return list; + return [{ name: '', owner: address }]; + } catch { + return [{ name: '', owner: address }]; + } +} + +export async function getPrimaryAccountName(address: string): Promise { + try { + const res = await qortalRequest({ + action: 'GET_PRIMARY_NAME', + address, + }); + return typeof res === 'string' ? res : ''; + } catch { + return ''; + } +} diff --git a/src/wrappers/GlobalWrapper.tsx b/src/wrappers/GlobalWrapper.tsx index d365782..6990eec 100644 --- a/src/wrappers/GlobalWrapper.tsx +++ b/src/wrappers/GlobalWrapper.tsx @@ -1,4 +1,9 @@ import React, { useEffect, useRef, useState } from "react"; +import { + getAccountNames, + getPrimaryAccountName, + NameRecord, +} from "../utils/qortalRequestFunctions"; import { useDispatch, useSelector } from "react-redux"; import { addUser } from "../state/features/authSlice"; @@ -12,7 +17,7 @@ import ConsentModal from "../components/modals/ConsentModal"; import { AudioPlayer } from "../components/common/AudioPlayer"; import { setPrivateGroups } from "../state/features/globalSlice"; import { LoaderBar } from "../components/common/LoaderBar"; -import { addAllHashMapSubject } from "../state/features/mailSlice"; +import { addAllHashMapSubject, clearMessages } from "../state/features/mailSlice"; interface Props { children: React.ReactNode; } @@ -62,22 +67,21 @@ const GlobalWrapper: React.FC = ({ children }) => { } }; + const switchActiveName = React.useCallback( + async (newName: string) => { + if (!user) return; + dispatch(addUser({ ...user, name: newName })); + getLocalSubjects(newName); + }, + [user] + ); + const isLoadingGlobal = useSelector( (state: RootState) => state.global.isLoadingGlobal ); const isLoadingCustom = useSelector( (state: RootState) => state.global.isLoadingCustom ); - async function getNameInfo(address: string) { - const response = await fetch("/names/address/" + address); - const nameData = await response.json(); - - if (nameData?.length > 0) { - return nameData[0].name; - } else { - return ""; - } - } const privateGroupsRef = React.useRef({}); @@ -245,12 +249,13 @@ const GlobalWrapper: React.FC = ({ children }) => { action: "GET_USER_ACCOUNT", }); - const name = await getNameInfo(account.address); - dispatch(addUser({ ...account, name })); + const names = await getAccountNames(account.address); + const primary = await getPrimaryAccountName(account.address); + dispatch(addUser({ ...account, name: primary, names })); getGroups(account.address); checkGroupMembers(account.address); - if (name) { - getLocalSubjects(name); + if (primary) { + getLocalSubjects(primary); } } catch (error) { console.error(error); @@ -268,6 +273,11 @@ const GlobalWrapper: React.FC = ({ children }) => { { + dispatch(clearMessages()); + dispatch(addUser({ ...user, name })); + }} userAvatar={userAvatar} authenticate={askForAccountInformation} /> -- 2.43.0