forked from Qortal/q-mail
Add multiple name support #1
@@ -33,13 +33,17 @@ interface Props {
|
|||||||
userName: string | null
|
userName: string | null
|
||||||
userAvatar: string
|
userAvatar: string
|
||||||
authenticate: () => void
|
authenticate: () => void
|
||||||
|
accountNames: { name: string }[]
|
||||||
|
setActiveName: (name: string) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const NavBar: React.FC<Props> = ({
|
const NavBar: React.FC<Props> = ({
|
||||||
isAuthenticated,
|
isAuthenticated,
|
||||||
userName,
|
userName,
|
||||||
userAvatar,
|
userAvatar,
|
||||||
authenticate
|
authenticate,
|
||||||
|
accountNames,
|
||||||
|
setActiveName
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
@@ -134,6 +138,21 @@ const NavBar: React.FC<Props> = ({
|
|||||||
horizontal: 'left'
|
horizontal: 'left'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{accountNames
|
||||||
|
.filter(n => n.name)
|
||||||
|
.map(n => (
|
||||||
|
<DropdownContainer
|
||||||
|
key={n.name}
|
||||||
|
onClick={() => {
|
||||||
|
setActiveName(n.name)
|
||||||
|
handleClose()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DropdownText>
|
||||||
|
{n.name === userName ? "✔︎ " : ""}{n.name}
|
||||||
|
</DropdownText>
|
||||||
|
</DropdownContainer>
|
||||||
|
))}
|
||||||
<DropdownContainer
|
<DropdownContainer
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsOpenModal(true)
|
setIsOpenModal(true)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import Tabs from '@mui/material/Tabs'
|
|||||||
import Tab from '@mui/material/Tab'
|
import Tab from '@mui/material/Tab'
|
||||||
import { useFetchMail } from '../../hooks/useFetchMail'
|
import { useFetchMail } from '../../hooks/useFetchMail'
|
||||||
import { ShowMessage } from './ShowMessage'
|
import { ShowMessage } from './ShowMessage'
|
||||||
import { addToHashMapMail } from '../../state/features/mailSlice'
|
import { addToHashMapMail, clearMessages } from '../../state/features/mailSlice'
|
||||||
import {
|
import {
|
||||||
setIsLoadingGlobal,
|
setIsLoadingGlobal,
|
||||||
setUserAvatarHash
|
setUserAvatarHash
|
||||||
@@ -269,6 +269,7 @@ export const AliasMail = ({ value, onOpen, messageOpenedId}: AliasMailProps) =>
|
|||||||
const firstMount = useRef<null | string>(null)
|
const firstMount = useRef<null | string>(null)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user?.name && (!firstMount.current || firstMount.current !== value)) {
|
if (user?.name && (!firstMount.current || firstMount.current !== value)) {
|
||||||
|
dispatch(clearMessages());
|
||||||
setMailMessages([])
|
setMailMessages([])
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
getMessages()
|
getMessages()
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import Tabs from "@mui/material/Tabs";
|
|||||||
import Tab from "@mui/material/Tab";
|
import Tab from "@mui/material/Tab";
|
||||||
import { useFetchMail } from "../../hooks/useFetchMail";
|
import { useFetchMail } from "../../hooks/useFetchMail";
|
||||||
import { ShowMessage } from "./ShowMessage";
|
import { ShowMessage } from "./ShowMessage";
|
||||||
|
import { clearMessages } from '../../state/features/mailSlice'
|
||||||
|
|
||||||
import SimpleTable from "./MailTable";
|
import SimpleTable from "./MailTable";
|
||||||
import { AliasMail } from "./AliasMail";
|
import { AliasMail } from "./AliasMail";
|
||||||
@@ -364,12 +365,16 @@ export const Mail = ({ isFromTo }: MailProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const firstMount = useRef(false);
|
const firstMount = useRef(false);
|
||||||
|
const prevName = useRef<string>();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user?.name && !firstMount.current) {
|
if (!user?.name) return;
|
||||||
|
if (!firstMount.current || prevName.current !== user.name) {
|
||||||
|
dispatch(clearMessages());
|
||||||
getMessages(true);
|
getMessages(true);
|
||||||
firstMount.current = true;
|
firstMount.current = true;
|
||||||
}
|
}
|
||||||
}, [user]);
|
prevName.current = user.name;
|
||||||
|
}, [user?.name]);
|
||||||
|
|
||||||
function a11yProps(index: number) {
|
function a11yProps(index: number) {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import Tabs from '@mui/material/Tabs'
|
|||||||
import Tab from '@mui/material/Tab'
|
import Tab from '@mui/material/Tab'
|
||||||
import { useFetchMail } from '../../hooks/useFetchMail'
|
import { useFetchMail } from '../../hooks/useFetchMail'
|
||||||
import { ShowMessage } from './ShowMessage'
|
import { ShowMessage } from './ShowMessage'
|
||||||
import { addToHashMapMail } from '../../state/features/mailSlice'
|
import { addToHashMapMail, clearMessages } from '../../state/features/mailSlice'
|
||||||
import {
|
import {
|
||||||
setIsLoadingGlobal,
|
setIsLoadingGlobal,
|
||||||
setUserAvatarHash
|
setUserAvatarHash
|
||||||
@@ -223,12 +223,16 @@ export const SentMail = ({onOpen}: SentMailProps) => {
|
|||||||
}, [getMailMessages, user])
|
}, [getMailMessages, user])
|
||||||
|
|
||||||
const firstMount = useRef(false);
|
const firstMount = useRef(false);
|
||||||
|
const prevName = useRef<string>();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (user?.name && !firstMount.current) {
|
if (!user?.name) return;
|
||||||
|
if (!firstMount.current || prevName.current !== user.name) {
|
||||||
|
dispatch(clearMessages());
|
||||||
getMessages(true);
|
getMessages(true);
|
||||||
firstMount.current = true;
|
firstMount.current = true;
|
||||||
}
|
}
|
||||||
}, [user]);
|
prevName.current = user.name;
|
||||||
|
}, [user?.name]);
|
||||||
|
|
||||||
const interval = useRef<any>(null)
|
const interval = useRef<any>(null)
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
|
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 {
|
interface AuthState {
|
||||||
user: {
|
user: User | null;
|
||||||
address: string;
|
|
||||||
publicKey: string;
|
|
||||||
name?: string;
|
|
||||||
} | null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: AuthState = {
|
const initialState: AuthState = {
|
||||||
user: null
|
user: null
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -202,6 +202,10 @@ export const mailSlice = createSlice({
|
|||||||
const subject = action.payload
|
const subject = action.payload
|
||||||
state.hashMapSavedSubjects[subject.id] = subject
|
state.hashMapSavedSubjects[subject.id] = subject
|
||||||
},
|
},
|
||||||
|
clearMessages: (state) => {
|
||||||
|
state.mailMessages = [];
|
||||||
|
state.hashMapMailMessages = {};
|
||||||
|
},
|
||||||
updateInHashMap: (state, action) => {
|
updateInHashMap: (state, action) => {
|
||||||
const { id } = action.payload
|
const { id } = action.payload
|
||||||
const post = action.payload
|
const post = action.payload
|
||||||
@@ -359,7 +363,8 @@ export const {
|
|||||||
addToHashMapMail,
|
addToHashMapMail,
|
||||||
upsertMessagesBeginning,
|
upsertMessagesBeginning,
|
||||||
addAllHashMapSubject,
|
addAllHashMapSubject,
|
||||||
addToHashMapSubject
|
addToHashMapSubject,
|
||||||
|
clearMessages
|
||||||
} = mailSlice.actions
|
} = mailSlice.actions
|
||||||
|
|
||||||
export default mailSlice.reducer
|
export default mailSlice.reducer
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
export interface NameRecord {
|
||||||
|
name: string;
|
||||||
|
owner: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getAccountNames(address: string): Promise<NameRecord[]> {
|
||||||
|
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<string> {
|
||||||
|
try {
|
||||||
|
const res = await qortalRequest({
|
||||||
|
action: 'GET_PRIMARY_NAME',
|
||||||
|
address,
|
||||||
|
});
|
||||||
|
return typeof res === 'string' ? res : '';
|
||||||
|
} catch {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
|
import {
|
||||||
|
getAccountNames,
|
||||||
|
getPrimaryAccountName,
|
||||||
|
NameRecord,
|
||||||
|
} from "../utils/qortalRequestFunctions";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useDispatch, useSelector } from "react-redux";
|
||||||
|
|
||||||
import { addUser } from "../state/features/authSlice";
|
import { addUser } from "../state/features/authSlice";
|
||||||
@@ -12,7 +17,7 @@ import ConsentModal from "../components/modals/ConsentModal";
|
|||||||
import { AudioPlayer } from "../components/common/AudioPlayer";
|
import { AudioPlayer } from "../components/common/AudioPlayer";
|
||||||
import { setPrivateGroups } from "../state/features/globalSlice";
|
import { setPrivateGroups } from "../state/features/globalSlice";
|
||||||
import { LoaderBar } from "../components/common/LoaderBar";
|
import { LoaderBar } from "../components/common/LoaderBar";
|
||||||
import { addAllHashMapSubject } from "../state/features/mailSlice";
|
import { addAllHashMapSubject, clearMessages } from "../state/features/mailSlice";
|
||||||
interface Props {
|
interface Props {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
@@ -62,22 +67,21 @@ const GlobalWrapper: React.FC<Props> = ({ children }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const switchActiveName = React.useCallback(
|
||||||
|
async (newName: string) => {
|
||||||
|
if (!user) return;
|
||||||
|
dispatch(addUser({ ...user, name: newName }));
|
||||||
|
getLocalSubjects(newName);
|
||||||
|
},
|
||||||
|
[user]
|
||||||
|
);
|
||||||
|
|
||||||
const isLoadingGlobal = useSelector(
|
const isLoadingGlobal = useSelector(
|
||||||
(state: RootState) => state.global.isLoadingGlobal
|
(state: RootState) => state.global.isLoadingGlobal
|
||||||
);
|
);
|
||||||
const isLoadingCustom = useSelector(
|
const isLoadingCustom = useSelector(
|
||||||
(state: RootState) => state.global.isLoadingCustom
|
(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<any>({});
|
const privateGroupsRef = React.useRef<any>({});
|
||||||
|
|
||||||
@@ -245,12 +249,13 @@ const GlobalWrapper: React.FC<Props> = ({ children }) => {
|
|||||||
action: "GET_USER_ACCOUNT",
|
action: "GET_USER_ACCOUNT",
|
||||||
});
|
});
|
||||||
|
|
||||||
const name = await getNameInfo(account.address);
|
const names = await getAccountNames(account.address);
|
||||||
dispatch(addUser({ ...account, name }));
|
const primary = await getPrimaryAccountName(account.address);
|
||||||
|
dispatch(addUser({ ...account, name: primary, names }));
|
||||||
getGroups(account.address);
|
getGroups(account.address);
|
||||||
checkGroupMembers(account.address);
|
checkGroupMembers(account.address);
|
||||||
if (name) {
|
if (primary) {
|
||||||
getLocalSubjects(name);
|
getLocalSubjects(primary);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@@ -268,6 +273,11 @@ const GlobalWrapper: React.FC<Props> = ({ children }) => {
|
|||||||
<NavBar
|
<NavBar
|
||||||
isAuthenticated={!!user}
|
isAuthenticated={!!user}
|
||||||
userName={user?.name || ""}
|
userName={user?.name || ""}
|
||||||
|
accountNames={user?.names || []}
|
||||||
|
setActiveName={(name: string) => {
|
||||||
|
dispatch(clearMessages());
|
||||||
|
dispatch(addUser({ ...user, name }));
|
||||||
|
}}
|
||||||
userAvatar={userAvatar}
|
userAvatar={userAvatar}
|
||||||
authenticate={askForAccountInformation}
|
authenticate={askForAccountInformation}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user