From 51802fa03dd518693f320a7f3569833a4eaaf933 Mon Sep 17 00:00:00 2001 From: Szymon Szlachtowicz <38212223+Szymx95@users.noreply.github.com> Date: Tue, 21 Dec 2021 13:39:46 +0100 Subject: [PATCH] Add user creation modal (#159) --- packages/react-chat/src/components/Chat.tsx | 2 + .../src/components/Chat/ChatCreation.tsx | 5 +- .../components/Chat/ChatMessageContent.tsx | 2 +- .../react-chat/src/components/ChatLoader.tsx | 10 +- .../src/components/Form/ContactMenu.tsx | 2 +- .../src/components/Form/IdentityLoader.tsx | 8 +- .../src/components/Icons/ColorChatIcon.tsx | 26 ++-- .../src/components/Members/MembersList.tsx | 8 +- .../src/components/Members/UserLogo.tsx | 70 +++++++++++ .../src/components/Messages/UiMessage.tsx | 13 +- .../Modals/{ModalStyle.ts => ModalStyle.tsx} | 31 +++++ .../src/components/Modals/ProfileModal.tsx | 44 +------ .../components/Modals/UserCreationModal.tsx | 117 ++++++++++++++++++ .../components/UserCreation/UserCreation.tsx | 10 +- .../src/contexts/identityProvider.tsx | 44 +++++-- .../src/contexts/messengerProvider.tsx | 9 +- .../src/hooks/messenger/useContacts.ts | 19 ++- .../src/hooks/messenger/useLoadPrevDay.ts | 2 +- .../src/hooks/messenger/useMessenger.ts | 6 +- packages/react-chat/src/styles/Inputs.ts | 10 ++ packages/react-chat/src/styles/themes.ts | 3 + packages/status-communities/src/contacts.ts | 52 +++++++- packages/status-communities/src/messenger.ts | 6 +- 23 files changed, 387 insertions(+), 112 deletions(-) create mode 100644 packages/react-chat/src/components/Members/UserLogo.tsx rename packages/react-chat/src/components/Modals/{ModalStyle.ts => ModalStyle.tsx} (65%) create mode 100644 packages/react-chat/src/components/Modals/UserCreationModal.tsx create mode 100644 packages/react-chat/src/styles/Inputs.ts diff --git a/packages/react-chat/src/components/Chat.tsx b/packages/react-chat/src/components/Chat.tsx index 2fdeb6d..64d4248 100644 --- a/packages/react-chat/src/components/Chat.tsx +++ b/packages/react-chat/src/components/Chat.tsx @@ -13,6 +13,7 @@ import { Members } from "./Members/Members"; import { CommunityModal } from "./Modals/CommunityModal"; import { EditModal } from "./Modals/EditModal"; import { ProfileModal } from "./Modals/ProfileModal"; +import { UserCreationModal } from "./Modals/UserCreationModal"; import { ToastMessageList } from "./ToastMessages/ToastMessageList"; import { UserCreation } from "./UserCreation/UserCreation"; @@ -20,6 +21,7 @@ function Modals() { return ( <> + diff --git a/packages/react-chat/src/components/Chat/ChatCreation.tsx b/packages/react-chat/src/components/Chat/ChatCreation.tsx index f8afabe..fdc0a68 100644 --- a/packages/react-chat/src/components/Chat/ChatCreation.tsx +++ b/packages/react-chat/src/components/Chat/ChatCreation.tsx @@ -23,8 +23,9 @@ export function ChatCreation({ const identity = useIdentity(); const [query, setQuery] = useState(""); const [styledGroup, setStyledGroup] = useState( - activeChannel?.members?.map((member) => member?.customName ?? member.id) ?? - [] + activeChannel?.members?.map( + (member) => member?.customName ?? member.trueName + ) ?? [] ); const { contacts, createGroupChat, addMembers } = useMessengerContext(); const setChatState = useChatState()[1]; diff --git a/packages/react-chat/src/components/Chat/ChatMessageContent.tsx b/packages/react-chat/src/components/Chat/ChatMessageContent.tsx index 38cddc1..bed14e7 100644 --- a/packages/react-chat/src/components/Chat/ChatMessageContent.tsx +++ b/packages/react-chat/src/components/Chat/ChatMessageContent.tsx @@ -34,7 +34,7 @@ export function Mention({ id, setMentioned, className }: MentionProps) { return ( setShowMenu(!showMenu)} className={className}> - {`@${contact?.customName ?? contact.id}`} + {`@${contact?.customName ?? contact.trueName}`} {showMenu && } ); diff --git a/packages/react-chat/src/components/ChatLoader.tsx b/packages/react-chat/src/components/ChatLoader.tsx index 4583d9d..54d1f8e 100644 --- a/packages/react-chat/src/components/ChatLoader.tsx +++ b/packages/react-chat/src/components/ChatLoader.tsx @@ -1,5 +1,4 @@ -import React, { useState } from "react"; -import { Identity } from "status-communities/dist/cjs"; +import React from "react"; import { ChatStateProvider } from "../contexts/chatStateProvider"; import { IdentityProvider } from "../contexts/identityProvider"; @@ -17,13 +16,12 @@ interface ChatLoaderProps { } export function ChatLoader({ communityKey }: ChatLoaderProps) { - const [identity, setIdentity] = useState(undefined); const [userCreationState] = useUserCreationState(); if (userCreationState === UserCreationState.NotCreating) return ( - - + + @@ -31,7 +29,7 @@ export function ChatLoader({ communityKey }: ChatLoaderProps) { ); if (userCreationState === UserCreationState.Creating) { - return ; + return ; } return null; diff --git a/packages/react-chat/src/components/Form/ContactMenu.tsx b/packages/react-chat/src/components/Form/ContactMenu.tsx index 047aa17..e9d2e97 100644 --- a/packages/react-chat/src/components/Form/ContactMenu.tsx +++ b/packages/react-chat/src/components/Form/ContactMenu.tsx @@ -43,7 +43,7 @@ export function ContactMenu({ id, setShowMenu }: ContactMenuProps) { - {contact?.customName ?? id.slice(0, 10)} + {contact?.customName ?? contact.trueName} {contact.isUntrustworthy && } {contact?.customName && ( diff --git a/packages/react-chat/src/components/Form/IdentityLoader.tsx b/packages/react-chat/src/components/Form/IdentityLoader.tsx index 68bdb40..de72173 100644 --- a/packages/react-chat/src/components/Form/IdentityLoader.tsx +++ b/packages/react-chat/src/components/Form/IdentityLoader.tsx @@ -2,6 +2,7 @@ import React, { useCallback, useEffect, useState } from "react"; import { Identity } from "status-communities/dist/cjs"; import styled from "styled-components"; +import { useSetIdentity } from "../../contexts/identityProvider"; import { UserCreationState, useUserCreationState, @@ -12,11 +13,8 @@ import { saveIdentity, } from "../../utils"; -interface IdentityLoaderProps { - setIdentity: (e: Identity) => void; -} - -export function IdentityLoader({ setIdentity }: IdentityLoaderProps) { +export function IdentityLoader() { + const setIdentity = useSetIdentity(); const [password, setPassword] = useState(""); const state = useUserCreationState(); diff --git a/packages/react-chat/src/components/Icons/ColorChatIcon.tsx b/packages/react-chat/src/components/Icons/ColorChatIcon.tsx index 2b02f8b..af0e6a8 100644 --- a/packages/react-chat/src/components/Icons/ColorChatIcon.tsx +++ b/packages/react-chat/src/components/Icons/ColorChatIcon.tsx @@ -15,7 +15,7 @@ export function ColorChatSvg({ width, height }: ColorChatSvgProps) { fill="none" xmlns="http://www.w3.org/2000/svg" > - + - - + + - - + + - - + + - - + + - - + + - - + + { if (identity) { return Object.values(contacts).filter( @@ -42,9 +42,7 @@ export function MembersList({ switchShowMembers }: MembersListProps) { - {identity && ( - {utils.bufToHex(identity.publicKey)} - )} + {identity && {nickname}} {onlineContacts.length > 0 && ( diff --git a/packages/react-chat/src/components/Members/UserLogo.tsx b/packages/react-chat/src/components/Members/UserLogo.tsx new file mode 100644 index 0000000..5c30cc5 --- /dev/null +++ b/packages/react-chat/src/components/Members/UserLogo.tsx @@ -0,0 +1,70 @@ +import React, { useMemo } from "react"; +import styled from "styled-components"; + +type UserLogoProps = { + radius: number; + colorWheel: [string, number][]; + icon?: string; + text?: string; +}; + +export function UserLogo({ icon, text, radius, colorWheel }: UserLogoProps) { + const conicGradient = useMemo(() => { + const colors = colorWheel + .map((color, idx) => { + const prevDeg = idx === 0 ? "0deg" : `${colorWheel[idx - 1][1]}deg`; + return `${color[0]} ${prevDeg} ${color[1]}deg`; + }) + .join(","); + return `conic-gradient(${colors})`; + }, [colorWheel]); + return ( + + + {!icon && text && {text}} + + + ); +} + +const TextWrapper = styled.div` + font-family: Inter; + font-style: normal; + font-weight: bold; + font-size: 32px; + line-height: 38px; + display: flex; + align-items: center; + text-align: center; + letter-spacing: -0.4px; + color: rgba(255, 255, 255, 0.7); +`; + +const Logo = styled.div<{ radius: number; icon?: string }>` + width: calc(${({ radius }) => radius}px - 6px); + height: calc(${({ radius }) => radius}px - 6px); + align-items: center; + justify-content: center; + flex-shrink: 0; + border-radius: 50%; + font-weight: bold; + font-size: 15px; + line-height: 20px; + background-color: ${({ theme }) => theme.logoColor}; + background-size: cover; + background-repeat: no-repeat; + background-image: ${({ icon }) => icon && `url(${icon}`}; + color: ${({ theme }) => theme.iconTextColor}; + margin: auto; + display: flex; +`; + +const Wrapper = styled.div<{ radius: number; conicGradient: string }>` + width: ${({ radius }) => radius}px; + height: ${({ radius }) => radius}px; + display: flex; + margin-left: auto; + margin-right: auto; + border-radius: 50%; + background: ${({ conicGradient }) => conicGradient}; +`; diff --git a/packages/react-chat/src/components/Messages/UiMessage.tsx b/packages/react-chat/src/components/Messages/UiMessage.tsx index 83cd364..78b715c 100644 --- a/packages/react-chat/src/components/Messages/UiMessage.tsx +++ b/packages/react-chat/src/components/Messages/UiMessage.tsx @@ -121,15 +121,10 @@ export function UiMessage({ - - {" "} - {contact?.customName ?? message.sender.slice(0, 10)} - - {contact?.customName && ( - - {message.sender.slice(0, 5)}...{message.sender.slice(-3)} - - )} + {contact?.customName ?? contact.trueName} + + {message.sender.slice(0, 5)}...{message.sender.slice(-3)} + {contact.isUntrustworthy && } {message.date.toLocaleString()} diff --git a/packages/react-chat/src/components/Modals/ModalStyle.ts b/packages/react-chat/src/components/Modals/ModalStyle.tsx similarity index 65% rename from packages/react-chat/src/components/Modals/ModalStyle.ts rename to packages/react-chat/src/components/Modals/ModalStyle.tsx index 8e22667..4cc291d 100644 --- a/packages/react-chat/src/components/Modals/ModalStyle.ts +++ b/packages/react-chat/src/components/Modals/ModalStyle.tsx @@ -1,5 +1,6 @@ import styled, { css } from "styled-components"; +import { buttonStyles } from "../Buttons/buttonStyle"; import { textMediumStyles } from "../Text"; export const Section = styled.div` @@ -23,6 +24,36 @@ export const Text = styled.p` ${textMediumStyles} `; +export const Btn = styled.button` + padding: 11px 24px; + margin-left: 8px; + ${buttonStyles} + + &:hover { + background: ${({ theme }) => theme.buttonBgHover}; + } + + &:disabled { + background: ${({ theme }) => theme.border}; + color: ${({ theme }) => theme.secondary}; + } +`; + +export 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}; + } +`; + export const ButtonSection = styled(Section)` display: flex; justify-content: flex-end; diff --git a/packages/react-chat/src/components/Modals/ProfileModal.tsx b/packages/react-chat/src/components/Modals/ProfileModal.tsx index e497b22..dd143cb 100644 --- a/packages/react-chat/src/components/Modals/ProfileModal.tsx +++ b/packages/react-chat/src/components/Modals/ProfileModal.tsx @@ -7,6 +7,7 @@ import { useIdentity } from "../../contexts/identityProvider"; import { useModal } from "../../contexts/modalProvider"; import { useToasts } from "../../contexts/toastProvider"; import { useManageContact } from "../../hooks/useManageContact"; +import { NameInput } from "../../styles/Inputs"; import { copy } from "../../utils"; import { buttonStyles } from "../Buttons/buttonStyle"; import { ClearSvg } from "../Icons/ClearIcon"; @@ -19,6 +20,8 @@ import { textMediumStyles, textSmallStyles } from "../Text"; import { Modal } from "./Modal"; import { + BackBtn, + Btn, ButtonSection, Heading, Hint, @@ -84,7 +87,7 @@ export const ProfileModal = () => { className={`${!requestCreation && "profile"}`} >
- {id.slice(0, 10)}’s Profile + {contact.trueName}’s Profile
@@ -101,7 +104,7 @@ export const ProfileModal = () => { )} - {contact?.customName ?? id.slice(0, 10)} + {contact?.customName ?? contact.trueName} {contact.isUntrustworthy && } {!renaming && ( @@ -402,36 +405,6 @@ const CopyButton = styled.button` } `; -const Btn = styled.button` - padding: 11px 24px; - margin-left: 8px; - ${buttonStyles} - - &: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; @@ -448,13 +421,6 @@ const NameInputWrapper = styled.div` position: relative; `; -const NameInput = styled.input` - width: 328px; - padding: 11px 16px; - - ${inputStyles} -`; - const RequestSection = styled.div` width: 100%; display: flex; diff --git a/packages/react-chat/src/components/Modals/UserCreationModal.tsx b/packages/react-chat/src/components/Modals/UserCreationModal.tsx new file mode 100644 index 0000000..5e68eea --- /dev/null +++ b/packages/react-chat/src/components/Modals/UserCreationModal.tsx @@ -0,0 +1,117 @@ +import React, { useState } from "react"; +import { Identity } from "status-communities/dist/cjs"; +import styled from "styled-components"; + +import { + useSetIdentity, + useSetNikcname, +} from "../../contexts/identityProvider"; +import { useModal } from "../../contexts/modalProvider"; +import { NameInput } from "../../styles/Inputs"; +import { LeftIconSvg } from "../Icons/LeftIcon"; +import { UserLogo } from "../Members/UserLogo"; + +import { Modal } from "./Modal"; +import { + BackBtn, + Btn, + ButtonSection, + Heading, + Hint, + Section, + Text, +} from "./ModalStyle"; + +export const UserCreationModalName = "UserCreationModal"; + +export function UserCreationModal() { + const setIdentity = useSetIdentity(); + const setNickname = useSetNikcname(); + + const [customNameInput, setCustomNameInput] = useState(""); + const { setModal } = useModal(UserCreationModalName); + return ( + +
+ Create a Status Profile +
+ + + Your profile + + Longer and unusual names are better as they are less likely to be + used by someone else. + + + + + setCustomNameInput(e.currentTarget.value)} + /> + + + + setModal(false)}> + + + { + setIdentity(Identity.generate()); + setNickname(customNameInput); + setModal(false); + }} + > + Next + + +
+ ); +} + +const MiddleSection = styled(Section)` + margin-bottom: 102px; +`; + +const LogoWrapper = styled.div` + position: relative; + display: flex; + margin-top: 32px; + margin-bottom: 38px; +`; + +const StyledHint = styled(Hint)` + font-family: Inter; + font-style: normal; + font-weight: normal; + font-size: 15px; + line-height: 22px; + text-align: center; +`; + +const Title = styled(Text)` + font-family: Inter; + font-style: normal; + font-weight: bold; + font-size: 22px; + line-height: 30px; + + text-align: center; + letter-spacing: -0.2px; + margin-bottom: 16px; +`; + +const Content = styled.div` + margin-top: 16px; + margin-left: 65px; + margin-right: 65px; +`; diff --git a/packages/react-chat/src/components/UserCreation/UserCreation.tsx b/packages/react-chat/src/components/UserCreation/UserCreation.tsx index 279a199..bc3b478 100644 --- a/packages/react-chat/src/components/UserCreation/UserCreation.tsx +++ b/packages/react-chat/src/components/UserCreation/UserCreation.tsx @@ -1,14 +1,12 @@ import React from "react"; import styled from "styled-components"; -import { - UserCreationState, - useUserCreationState, -} from "../../contexts/userCreationStateProvider"; +import { useModal } from "../../contexts/modalProvider"; import { ColorChatIcon } from "../Icons/ColorChatIcon"; +import { UserCreationModalName } from "../Modals/UserCreationModal"; export function UserCreation() { - const state = useUserCreationState(); + const { setModal } = useModal(UserCreationModalName); return ( @@ -16,7 +14,7 @@ export function UserCreation() { Want in on the discussion ? - state[1](UserCreationState.Creating)}> + setModal(true)}> Use a throwaway account diff --git a/packages/react-chat/src/contexts/identityProvider.tsx b/packages/react-chat/src/contexts/identityProvider.tsx index cdc8e13..9b0e5b3 100644 --- a/packages/react-chat/src/contexts/identityProvider.tsx +++ b/packages/react-chat/src/contexts/identityProvider.tsx @@ -1,20 +1,46 @@ -import React, { createContext, useContext } from "react"; +import React, { createContext, useContext, useState } from "react"; import { Identity } from "status-communities/dist/cjs"; -const IdentityContext = createContext(undefined); +const IdentityContext = createContext<{ + identity: Identity | undefined; + setIdentity: React.Dispatch>; + nickname: string | undefined; + setNickname: React.Dispatch>; +}>({ + identity: undefined, + setIdentity: () => undefined, + nickname: undefined, + setNickname: () => undefined, +}); export function useIdentity() { - return useContext(IdentityContext); + return useContext(IdentityContext).identity; +} + +export function useSetIdentity() { + return useContext(IdentityContext).setIdentity; +} + +export function useNickname() { + return useContext(IdentityContext).nickname; +} + +export function useSetNikcname() { + return useContext(IdentityContext).setNickname; } interface IdentityProviderProps { children: React.ReactNode; - identity: Identity | undefined; } -export function IdentityProvider({ - children, - identity, -}: IdentityProviderProps) { - return ; +export function IdentityProvider({ children }: IdentityProviderProps) { + const [identity, setIdentity] = useState(undefined); + const [nickname, setNickname] = useState(undefined); + + return ( + + ); } diff --git a/packages/react-chat/src/contexts/messengerProvider.tsx b/packages/react-chat/src/contexts/messengerProvider.tsx index 49bb1ba..57c946e 100644 --- a/packages/react-chat/src/contexts/messengerProvider.tsx +++ b/packages/react-chat/src/contexts/messengerProvider.tsx @@ -1,8 +1,9 @@ import React, { createContext, useContext } from "react"; -import { Identity } from "status-communities/dist/cjs"; import { MessengerType, useMessenger } from "../hooks/messenger/useMessenger"; +import { useIdentity, useNickname } from "./identityProvider"; + const MessengerContext = createContext({ messenger: undefined, messages: [], @@ -37,14 +38,14 @@ export function useMessengerContext() { interface MessengerProviderProps { children: React.ReactNode; communityKey?: string; - identity?: Identity; } export function MessengerProvider({ children, communityKey, - identity, }: MessengerProviderProps) { - const messenger = useMessenger(communityKey, identity); + const identity = useIdentity(); + const nickname = useNickname(); + const messenger = useMessenger(communityKey, identity, nickname); return ; } diff --git a/packages/react-chat/src/hooks/messenger/useContacts.ts b/packages/react-chat/src/hooks/messenger/useContacts.ts index d8f2989..d7a6093 100644 --- a/packages/react-chat/src/hooks/messenger/useContacts.ts +++ b/packages/react-chat/src/hooks/messenger/useContacts.ts @@ -9,10 +9,11 @@ import { Contacts } from "../../models/Contact"; export function useContacts( messenger: Messenger | undefined, - identity: Identity | undefined + identity: Identity | undefined, + nickname: string | undefined ) { const [internalContacts, setInternalContacts] = useState<{ - [id: string]: number; + [id: string]: { clock: number; nickname?: string }; }>({}); const contactsClass = useMemo(() => { @@ -22,9 +23,15 @@ export function useContacts( messenger.waku, (id, clock) => { setInternalContacts((prev) => { - return { ...prev, [id]: clock }; + return { ...prev, [id]: { ...prev[id], clock } }; }); - } + }, + (id, nickname) => { + setInternalContacts((prev) => { + return { ...prev, [id]: { ...prev[id], nickname } }; + }); + }, + nickname ); return newContacts; } @@ -36,11 +43,11 @@ export function useContacts( const now = Date.now(); setContacts((prev) => { const newContacts: Contacts = {}; - Object.entries(internalContacts).forEach(([id, clock]) => { + Object.entries(internalContacts).forEach(([id, { clock, nickname }]) => { newContacts[id] = { id, online: clock > now - 301000, - trueName: id.slice(0, 10), + trueName: nickname ?? id.slice(0, 10), isUntrustworthy: false, blocked: false, }; diff --git a/packages/react-chat/src/hooks/messenger/useLoadPrevDay.ts b/packages/react-chat/src/hooks/messenger/useLoadPrevDay.ts index ee84afc..b00d2d0 100644 --- a/packages/react-chat/src/hooks/messenger/useLoadPrevDay.ts +++ b/packages/react-chat/src/hooks/messenger/useLoadPrevDay.ts @@ -24,7 +24,7 @@ export function useLoadPrevDay( async (id: string, groupChat?: boolean) => { if (messenger) { const endTime = lastLoadTime.current[id] ?? new Date(); - const startTime = new Date(endTime.getTime() - _MS_PER_DAY); + const startTime = new Date(endTime.getTime() - _MS_PER_DAY * 5); const timeDiff = Math.floor( (new Date().getTime() - endTime.getTime()) / _MS_PER_DAY ); diff --git a/packages/react-chat/src/hooks/messenger/useMessenger.ts b/packages/react-chat/src/hooks/messenger/useMessenger.ts index db681b0..59a9712 100644 --- a/packages/react-chat/src/hooks/messenger/useMessenger.ts +++ b/packages/react-chat/src/hooks/messenger/useMessenger.ts @@ -99,7 +99,8 @@ function useCreateCommunity( export function useMessenger( communityKey: string | undefined, - identity: Identity | undefined + identity: Identity | undefined, + nickname: string | undefined ) { const [activeChannel, setActiveChannel] = useState({ id: "", @@ -112,7 +113,8 @@ export function useMessenger( const { contacts, setContacts, contactsClass } = useContacts( messenger, - identity + identity, + nickname ); const { diff --git a/packages/react-chat/src/styles/Inputs.ts b/packages/react-chat/src/styles/Inputs.ts new file mode 100644 index 0000000..57d5a90 --- /dev/null +++ b/packages/react-chat/src/styles/Inputs.ts @@ -0,0 +1,10 @@ +import styled from "styled-components"; + +import { inputStyles } from "../components/Modals/ModalStyle"; + +export const NameInput = styled.input` + width: 328px; + padding: 11px 16px; + + ${inputStyles} +`; diff --git a/packages/react-chat/src/styles/themes.ts b/packages/react-chat/src/styles/themes.ts index cdc2d9e..f32e834 100644 --- a/packages/react-chat/src/styles/themes.ts +++ b/packages/react-chat/src/styles/themes.ts @@ -8,6 +8,7 @@ export type Theme = { iconColor: string; iconUserColor: string; iconTextColor: string; + logoColor: string; activeChannelBackground: string; notificationColor: string; inputColor: string; @@ -37,6 +38,7 @@ export const lightTheme: Theme = { iconColor: "#D37EF4", iconUserColor: "#717199", iconTextColor: "rgba(255, 255, 255, 0.7)", + logoColor: "#51D0F0", activeChannelBackground: "#E9EDF1", notificationColor: "#4360DF", inputColor: "#EEF2F5", @@ -66,6 +68,7 @@ export const darkTheme: Theme = { guestNameColor: "#887AF9", iconColor: "#D37EF4", iconUserColor: "#717199", + logoColor: "#51D0F0", iconTextColor: "rgba(0, 0, 0, 0.7)", activeChannelBackground: "#2C2C2C", notificationColor: "#887AF9", diff --git a/packages/status-communities/src/contacts.ts b/packages/status-communities/src/contacts.ts index e5d6f59..9914db4 100644 --- a/packages/status-communities/src/contacts.ts +++ b/packages/status-communities/src/contacts.ts @@ -1,9 +1,10 @@ -import { Waku, WakuMessage } from "js-waku"; +import { PageDirection, Waku, WakuMessage } from "js-waku"; import { idToContactCodeTopic } from "./contentTopic"; import { Identity } from "./identity"; import { StatusUpdate_StatusType } from "./proto/communities/v1/status_update"; import { bufToHex } from "./utils"; +import { ChatIdentity } from "./wire/chat_identity"; import { StatusUpdate } from "./wire/status_update"; const STATUS_BROADCAST_INTERVAL = 30000; @@ -11,7 +12,9 @@ const STATUS_BROADCAST_INTERVAL = 30000; export class Contacts { waku: Waku; identity: Identity | undefined; + nickname?: string; private callback: (publicKey: string, clock: number) => void; + private callbackNickname: (publicKey: string, nickname: string) => void; private contacts: string[] = []; /** @@ -30,11 +33,15 @@ export class Contacts { public constructor( identity: Identity | undefined, waku: Waku, - callback: (publicKey: string, clock: number) => void + callback: (publicKey: string, clock: number) => void, + callbackNickname: (publicKey: string, nickname: string) => void, + nickname?: string ) { this.waku = waku; this.identity = identity; + this.nickname = nickname; this.callback = callback; + this.callbackNickname = callbackNickname; this.startBroadcast(); if (identity) { this.addContact(bufToHex(identity.publicKey)); @@ -66,6 +73,26 @@ export class Contacts { endTime: now, }, }); + this.waku.store.queryHistory([idToContactCodeTopic(publicKey)], { + callback: (msgs) => + msgs.some((e) => { + try { + if (e.payload) { + const chatIdentity = ChatIdentity.decode(e?.payload); + if (chatIdentity) { + this.callbackNickname( + publicKey, + chatIdentity?.displayName ?? "" + ); + } + return true; + } + } catch { + return false; + } + }), + pageDirection: PageDirection.BACKWARD, + }); this.waku.relay.addObserver(callback, [idToContactCodeTopic(publicKey)]); } } @@ -84,6 +111,27 @@ export class Contacts { this.waku.relay.send(msg); } }; + + const sendNickname = async (): Promise => { + if (this.identity && this.nickname) { + const chatIdentity = new ChatIdentity({ + clock: new Date().getTime(), + color: "", + description: "", + emoji: "", + images: {}, + ensName: "", + displayName: this?.nickname ?? "", + }); + const msg = await WakuMessage.fromBytes( + chatIdentity.encode(), + idToContactCodeTopic(bufToHex(this.identity.publicKey)), + { sigPrivKey: this.identity.privateKey } + ); + await this.waku.relay.send(msg); + } + }; + sendNickname(); send(); setInterval(send, STATUS_BROADCAST_INTERVAL); } diff --git a/packages/status-communities/src/messenger.ts b/packages/status-communities/src/messenger.ts index 88a69f4..1d9fc06 100644 --- a/packages/status-communities/src/messenger.ts +++ b/packages/status-communities/src/messenger.ts @@ -223,7 +223,7 @@ export class Messenger { callback(messages.filter(isDefined)); } }; - + console.log(`querying ${chat.contentTopic} for ${startTime} to ${endTime}`); const allMessages = await this.waku.store.queryHistory( [chat.contentTopic], { @@ -231,6 +231,10 @@ export class Messenger { callback: _callback, } ); + console.log( + `ended querying ${chat.contentTopic} for ${startTime} to ${endTime}` + ); + return allMessages.length; }