Contact renaming (#131)
This commit is contained in:
parent
3079487c02
commit
7fb0bfbdc7
|
@ -28,6 +28,9 @@ type ChatUiMessageProps = {
|
|||
setImage: (img: string) => void;
|
||||
setLink: (link: string) => void;
|
||||
setUser: (user: string) => void;
|
||||
customName?: string;
|
||||
trueName?: string;
|
||||
setRenaming: (val: boolean) => void;
|
||||
};
|
||||
|
||||
function ChatUiMessage({
|
||||
|
@ -37,6 +40,9 @@ function ChatUiMessage({
|
|||
setImage,
|
||||
setLink,
|
||||
setUser,
|
||||
customName,
|
||||
trueName,
|
||||
setRenaming,
|
||||
}: ChatUiMessageProps) {
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [isUntrustworthy, setIsUntrustworthy] = useState(false);
|
||||
|
@ -63,6 +69,9 @@ function ChatUiMessage({
|
|||
setShowMenu={setShowMenu}
|
||||
isUntrustworthy={isUntrustworthy}
|
||||
setIsUntrustworthy={setIsUntrustworthy}
|
||||
customName={customName}
|
||||
trueName={trueName}
|
||||
setRenaming={setRenaming}
|
||||
/>
|
||||
)}
|
||||
<UserIcon />
|
||||
|
@ -71,7 +80,15 @@ function ChatUiMessage({
|
|||
<ContentWrapper>
|
||||
<MessageHeaderWrapper>
|
||||
<UserNameWrapper>
|
||||
<UserName>{message.sender.slice(0, 10)}</UserName>
|
||||
<UserName>
|
||||
{" "}
|
||||
{customName ? customName : message.sender.slice(0, 10)}
|
||||
</UserName>
|
||||
{customName && (
|
||||
<UserAddress>
|
||||
{message.sender.slice(0, 5)}...{message.sender.slice(-3)}
|
||||
</UserAddress>
|
||||
)}
|
||||
{isUntrustworthy && <UntrustworthIcon />}
|
||||
</UserNameWrapper>
|
||||
<TimeWrapper>{message.date.toLocaleString()}</TimeWrapper>
|
||||
|
@ -119,11 +136,23 @@ export function ChatMessages() {
|
|||
);
|
||||
useEffect(() => (!showLinkModal ? setLink("") : undefined), [showLinkModal]);
|
||||
|
||||
const [renaming, setRenaming] = useState(false);
|
||||
const [customName, setCustomName] = useState("");
|
||||
const [trueName, setTrueName] = useState("");
|
||||
|
||||
return (
|
||||
<MessagesWrapper ref={ref}>
|
||||
<PictureModal image={image} />
|
||||
<LinkModal link={link} />
|
||||
<ProfileModal user={user} />
|
||||
<ProfileModal
|
||||
user={user}
|
||||
renaming={renaming}
|
||||
setRenaming={setRenaming}
|
||||
customName={customName}
|
||||
setCustomName={setCustomName}
|
||||
trueName={trueName}
|
||||
setTrueName={setTrueName}
|
||||
/>
|
||||
<EmptyChannel channel={activeChannel} />
|
||||
{loadingMessages && (
|
||||
<LoadingWrapper>
|
||||
|
@ -139,6 +168,9 @@ export function ChatMessages() {
|
|||
setLink={setLink}
|
||||
setImage={setImage}
|
||||
setUser={setUser}
|
||||
customName={customName}
|
||||
trueName={trueName}
|
||||
setRenaming={setRenaming}
|
||||
/>
|
||||
))}
|
||||
</MessagesWrapper>
|
||||
|
@ -226,6 +258,27 @@ const UserName = styled.p`
|
|||
${textMediumStyles}
|
||||
`;
|
||||
|
||||
export const UserAddress = styled.p`
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
letter-spacing: 0.2px;
|
||||
color: ${({ theme }) => theme.secondary};
|
||||
position: relative;
|
||||
padding-right: 8px;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
border-radius: 50%;
|
||||
background: ${({ theme }) => theme.secondary};
|
||||
}
|
||||
`;
|
||||
|
||||
const TimeWrapper = styled.div`
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
|
|
|
@ -5,7 +5,7 @@ import { useBlockedUsers } from "../../contexts/blockedUsersProvider";
|
|||
import { useFriends } from "../../contexts/friendsProvider";
|
||||
import { useModal } from "../../contexts/modalProvider";
|
||||
import { ChatMessage } from "../../models/ChatMessage";
|
||||
import { Icon } from "../Chat/ChatMessages";
|
||||
import { Icon, UserAddress } from "../Chat/ChatMessages";
|
||||
import { AddContactSvg } from "../Icons/AddContactIcon";
|
||||
import { BlockSvg } from "../Icons/BlockIcon";
|
||||
import { ChatSvg } from "../Icons/ChatIcon";
|
||||
|
@ -24,6 +24,9 @@ type ContactMenuProps = {
|
|||
setShowMenu: (val: boolean) => void;
|
||||
isUntrustworthy: boolean;
|
||||
setIsUntrustworthy: (val: boolean) => void;
|
||||
customName?: string;
|
||||
trueName?: string;
|
||||
setRenaming: (val: boolean) => void;
|
||||
};
|
||||
|
||||
export function ContactMenu({
|
||||
|
@ -31,6 +34,9 @@ export function ContactMenu({
|
|||
setShowMenu,
|
||||
isUntrustworthy,
|
||||
setIsUntrustworthy,
|
||||
customName,
|
||||
trueName,
|
||||
setRenaming,
|
||||
}: ContactMenuProps) {
|
||||
const id = message.sender;
|
||||
const { blockedUsers, setBlockedUsers } = useBlockedUsers();
|
||||
|
@ -59,9 +65,12 @@ export function ContactMenu({
|
|||
<UserIcon />
|
||||
)}
|
||||
<UserNameWrapper>
|
||||
<UserName>{message.sender.slice(0, 10)}</UserName>
|
||||
<UserName>
|
||||
{customName ? customName : message.sender.slice(0, 10)}
|
||||
</UserName>
|
||||
{isUntrustworthy && <UntrustworthIcon />}
|
||||
</UserNameWrapper>
|
||||
{trueName && <UserTrueName>({trueName})</UserTrueName>}
|
||||
<UserAddress>
|
||||
{message.sender.slice(0, 10)}...{message.sender.slice(-3)}
|
||||
</UserAddress>
|
||||
|
@ -83,7 +92,12 @@ export function ContactMenu({
|
|||
<MenuText>Send Message</MenuText>
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem>
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
setModal(true);
|
||||
setRenaming(true);
|
||||
}}
|
||||
>
|
||||
<EditSvg width={16} height={16} />
|
||||
<MenuText>Rename</MenuText>
|
||||
</MenuItem>
|
||||
|
@ -151,10 +165,10 @@ const UserName = styled.p`
|
|||
${textMediumStyles}
|
||||
`;
|
||||
|
||||
const UserAddress = styled.p`
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
letter-spacing: 0.2px;
|
||||
margin-bottom: 8px;
|
||||
color: ${({ theme }) => theme.secondary};
|
||||
const UserTrueName = styled.p`
|
||||
color: ${({ theme }) => theme.primary};
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
letter-spacing: 0.1px;
|
||||
margin-top: 4px;
|
||||
`;
|
||||
|
|
|
@ -13,7 +13,6 @@ export function ClearSvg({ height, width, className }: ClearSvgProps) {
|
|||
width={width}
|
||||
height={height}
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className={className}
|
||||
>
|
||||
|
@ -36,6 +35,14 @@ const Icon = styled(ClearSvg)`
|
|||
fill: ${({ theme }) => theme.tertiary};
|
||||
}
|
||||
|
||||
&.profile {
|
||||
fill: ${({ theme }) => theme.secondary};
|
||||
}
|
||||
|
||||
&.profile > path {
|
||||
fill: ${({ theme }) => theme.bodyBackgroundColor};
|
||||
}
|
||||
|
||||
&:hover > path {
|
||||
fill: ${({ theme }) => theme.bodyBackgroundColor};
|
||||
}
|
||||
|
|
|
@ -26,4 +26,6 @@ export const Text = styled.p`
|
|||
export const ButtonSection = styled(Section)`
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
`;
|
||||
|
|
|
@ -5,8 +5,10 @@ import { useBlockedUsers } from "../../contexts/blockedUsersProvider";
|
|||
import { useFriends } from "../../contexts/friendsProvider";
|
||||
import { copy } from "../../utils";
|
||||
import { buttonStyles } from "../Buttons/buttonStyle";
|
||||
import { ClearSvg } from "../Icons/ClearIcon";
|
||||
import { CopySvg } from "../Icons/CopyIcon";
|
||||
import { EditSvg } from "../Icons/EditIcon";
|
||||
import { LeftIconSvg } from "../Icons/LeftIcon";
|
||||
import { UntrustworthIcon } from "../Icons/UntrustworthIcon";
|
||||
import { UserIcon } from "../Icons/UserIcon";
|
||||
import { textMediumStyles } from "../Text";
|
||||
|
@ -19,9 +21,24 @@ export const ProfileModalName = "profileModal";
|
|||
interface ProfileModalProps {
|
||||
user: string;
|
||||
image?: string;
|
||||
renaming: boolean;
|
||||
customName?: string;
|
||||
trueName?: string;
|
||||
setRenaming: (val: boolean) => void;
|
||||
setTrueName: (val: string) => void;
|
||||
setCustomName: (val: string) => void;
|
||||
}
|
||||
|
||||
export const ProfileModal = ({ user, image }: ProfileModalProps) => {
|
||||
export const ProfileModal = ({
|
||||
user,
|
||||
image,
|
||||
renaming,
|
||||
customName,
|
||||
trueName,
|
||||
setRenaming,
|
||||
setTrueName,
|
||||
setCustomName,
|
||||
}: ProfileModalProps) => {
|
||||
const [isUntrustworthy, setIsUntrustworthy] = useState(false);
|
||||
|
||||
const { blockedUsers, setBlockedUsers } = useBlockedUsers();
|
||||
|
@ -41,7 +58,7 @@ export const ProfileModal = ({ user, image }: ProfileModalProps) => {
|
|||
<Heading>{user.slice(0, 10)}’s Profile</Heading>
|
||||
</Section>
|
||||
|
||||
<Section>
|
||||
<ProfileSection>
|
||||
<NameSection>
|
||||
{image ? (
|
||||
<ProfileIcon
|
||||
|
@ -53,12 +70,38 @@ export const ProfileModal = ({ user, image }: ProfileModalProps) => {
|
|||
<UserIcon />
|
||||
)}
|
||||
<UserNameWrapper>
|
||||
<UserName>{user.slice(0, 10)}</UserName>
|
||||
<UserName>{customName ? customName : user.slice(0, 10)}</UserName>
|
||||
{isUntrustworthy && <UntrustworthIcon />}
|
||||
{!renaming && (
|
||||
<button onClick={() => setRenaming(true)}>
|
||||
{" "}
|
||||
<EditSvg width={24} height={24} />
|
||||
</button>
|
||||
)}
|
||||
</UserNameWrapper>
|
||||
{trueName && <UserTrueName>{trueName}</UserTrueName>}
|
||||
{trueName && <button onClick={() => setTrueName("")}></button>}
|
||||
</NameSection>
|
||||
|
||||
{renaming ? (
|
||||
<NameInputWrapper>
|
||||
<NameInput
|
||||
placeholder="Only you will see this nickname"
|
||||
value={customName}
|
||||
onChange={(e) => setCustomName(e.currentTarget.value)}
|
||||
/>
|
||||
{customName && (
|
||||
<ClearBtn
|
||||
onClick={() => {
|
||||
setCustomName("");
|
||||
setTrueName("");
|
||||
}}
|
||||
>
|
||||
<ClearSvg width={16} height={16} className="profile" />
|
||||
</ClearBtn>
|
||||
)}
|
||||
</NameInputWrapper>
|
||||
) : (
|
||||
<>
|
||||
<UserAddressWrapper>
|
||||
<UserAddress>Chatkey: {user.slice(0, 30)}</UserAddress>
|
||||
|
||||
|
@ -66,10 +109,28 @@ export const ProfileModal = ({ user, image }: ProfileModalProps) => {
|
|||
<CopySvg width={24} height={24} />
|
||||
</CopyButton>
|
||||
</UserAddressWrapper>
|
||||
|
||||
<EmojiKey>🎩🍞🥑🦍🌈📡💅🏻♣️🔔⛸👵🅱</EmojiKey>
|
||||
</Section>
|
||||
<EmojiKey>🎩🍞🥑🦍🌈📡💅🏻♣️🔔⛸👵🅱</EmojiKey>{" "}
|
||||
</>
|
||||
)}
|
||||
</ProfileSection>
|
||||
<ButtonSection>
|
||||
{renaming ? (
|
||||
<>
|
||||
<BackBtn onClick={() => setRenaming(false)}>
|
||||
<LeftIconSvg width={28} height={28} />
|
||||
</BackBtn>
|
||||
<Btn
|
||||
disabled={!customName}
|
||||
onClick={() => {
|
||||
setTrueName(user.slice(0, 10));
|
||||
setRenaming(false);
|
||||
}}
|
||||
>
|
||||
Apply nickname
|
||||
</Btn>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{!userIsFriend && (
|
||||
<ProfileBtn
|
||||
className={userInBlocked ? "" : "red"}
|
||||
|
@ -85,7 +146,9 @@ export const ProfileModal = ({ user, image }: ProfileModalProps) => {
|
|||
{userIsFriend && (
|
||||
<ProfileBtn
|
||||
className="red"
|
||||
onClick={() => setFriends((prev) => prev.filter((e) => e != user))}
|
||||
onClick={() =>
|
||||
setFriends((prev) => prev.filter((e) => e != user))
|
||||
}
|
||||
>
|
||||
Remove Contact
|
||||
</ProfileBtn>
|
||||
|
@ -103,14 +166,23 @@ export const ProfileModal = ({ user, image }: ProfileModalProps) => {
|
|||
Send Contact Request
|
||||
</Btn>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</ButtonSection>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
const ProfileSection = styled(Section)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const NameSection = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
`;
|
||||
|
@ -150,6 +222,14 @@ const UserName = styled.p`
|
|||
margin-right: 8px;
|
||||
`;
|
||||
|
||||
const UserTrueName = styled.p`
|
||||
color: ${({ theme }) => theme.primary};
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
letter-spacing: 0.1px;
|
||||
margin-top: 8px;
|
||||
`;
|
||||
|
||||
const UserAddressWrapper = styled.div`
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
|
@ -211,4 +291,57 @@ const Btn = styled.button`
|
|||
&:hover {
|
||||
background: ${({ theme }) => theme.buttonBgHover};
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
background: ${({ theme }) => theme.border};
|
||||
color: ${({ theme }) => theme.secondary};
|
||||
}
|
||||
`;
|
||||
|
||||
const BackBtn = styled(Btn)`
|
||||
position: absolute;
|
||||
left: 16px;
|
||||
top: 16px;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 50%;
|
||||
padding: 8px;
|
||||
margin-left: 0;
|
||||
|
||||
& > svg {
|
||||
fill: ${({ theme }) => theme.tertiary};
|
||||
}
|
||||
`;
|
||||
|
||||
const ClearBtn = styled.button`
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
border-radius: 50%;
|
||||
|
||||
& > svg {
|
||||
fill: ${({ theme }) => theme.secondary};
|
||||
}
|
||||
`;
|
||||
|
||||
const NameInputWrapper = styled.div`
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
const NameInput = styled.input`
|
||||
width: 328px;
|
||||
padding: 11px 16px;
|
||||
background: ${({ theme }) => theme.inputColor};
|
||||
border-radius: 8px;
|
||||
border: 1px solid ${({ theme }) => theme.border};
|
||||
color: ${({ theme }) => theme.primary};
|
||||
outline: none;
|
||||
|
||||
${textMediumStyles}
|
||||
|
||||
&:focus {
|
||||
outline: 1px solid ${({ theme }) => theme.tertiary};
|
||||
caret-color: ${({ theme }) => theme.notificationColor};
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -4,6 +4,7 @@ import styled from "styled-components";
|
|||
|
||||
import { BlockedUsersProvider } from "../contexts/blockedUsersProvider";
|
||||
import { FetchMetadataProvider } from "../contexts/fetchMetadataProvider";
|
||||
import { FriendsProvider } from "../contexts/friendsProvider";
|
||||
import { ModalProvider } from "../contexts/modalProvider";
|
||||
import { NarrowProvider } from "../contexts/narrowProvider";
|
||||
import { Metadata } from "../models/Metadata";
|
||||
|
@ -29,6 +30,7 @@ export function ReactChat({
|
|||
<NarrowProvider myRef={ref}>
|
||||
<FetchMetadataProvider fetchMetadata={fetchMetadata}>
|
||||
<BlockedUsersProvider>
|
||||
<FriendsProvider>
|
||||
<ModalProvider>
|
||||
<Wrapper ref={ref}>
|
||||
<GlobalStyle />
|
||||
|
@ -36,6 +38,7 @@ export function ReactChat({
|
|||
<div id="modal-root" />
|
||||
</Wrapper>
|
||||
</ModalProvider>
|
||||
</FriendsProvider>
|
||||
</BlockedUsersProvider>
|
||||
</FetchMetadataProvider>
|
||||
</NarrowProvider>
|
||||
|
|
Loading…
Reference in New Issue