1
0
mirror of https://github.com/oceanprotocol/market.git synced 2024-12-02 05:57:29 +01:00

update direct message component

This commit is contained in:
marcoelissa 2022-12-09 21:19:16 +07:00
parent 20d587a249
commit 1f6c9a06a6
11 changed files with 252 additions and 98 deletions

View File

@ -27,7 +27,7 @@ type IOrbisProvider = {
unreadMessages: IOrbisNotification[]
connectOrbis: (lit?: boolean) => Promise<IOrbisProfile | null>
disconnectOrbis: () => void
checkConnection: (options: {
checkOrbisConnection: (options: {
autoConnect?: boolean
lit?: boolean
}) => Promise<IOrbisProfile>
@ -38,10 +38,7 @@ type IOrbisProvider = {
}>
setOpenConversations: (value: boolean) => void
setConversationId: (value: string) => void
setConversations: (value: IOrbisConversation[]) => void
getConversations: (did: string) => Promise<void>
createConversation: (value: string) => Promise<void>
checkConversation: (value: string) => Promise<IOrbisConversation[]>
getDid: (value: string) => Promise<string>
}
@ -67,17 +64,23 @@ function OrbisProvider({ children }: { children: ReactNode }): ReactElement {
(o) => o.stream_id === conversationId
)
if (conversation) {
const recipient = conversation.recipients_details.find(
const details = conversation.recipients_details.find(
(o: IOrbisProfile) => o.did !== account.did
)
const did = conversation.recipients.find(
(o: string) => o !== account.did
)
const address =
recipient?.metadata?.address || didToAddress(recipient?.did)
const address = didToAddress(did)
title =
recipient?.metadata?.ensName ||
recipient?.profile?.username ||
accountTruncate(address)
if (details) {
title =
details?.metadata?.ensName ||
details?.profile?.username ||
accountTruncate(address)
} else {
title = accountTruncate(address)
}
}
}
@ -95,6 +98,7 @@ function OrbisProvider({ children }: { children: ReactNode }): ReactElement {
if (res.status === 200) {
const { data } = await orbis.getProfile(res.did)
setAccount(data)
setHasLit(res.details.hasLit)
return data
} else {
await sleep(2000)
@ -115,7 +119,7 @@ function OrbisProvider({ children }: { children: ReactNode }): ReactElement {
return res
}
const checkConnection = async ({
const checkOrbisConnection = async ({
autoConnect,
lit
}: {
@ -141,25 +145,32 @@ function OrbisProvider({ children }: { children: ReactNode }): ReactElement {
context: CONVERSATION_CONTEXT
})
setConversations(data || [])
return data || []
}
// Only show conversations with exactly 2 unique participants and remove duplicates based on participants
const filteredConversations: IOrbisConversation[] = []
data.forEach((conversation: IOrbisConversation) => {
if (conversation.recipients.length === 2) {
const found = filteredConversations.find(
(o: IOrbisConversation) =>
o.recipients.length === 2 &&
o.recipients.includes(conversation.recipients[0]) &&
o.recipients.includes(conversation.recipients[1])
)
const checkConversation = async (userDid: string) => {
const filtered: IOrbisConversation[] = conversations.filter(
(conversation: IOrbisConversation) => {
return conversation.recipients.includes(userDid)
if (!found) {
filteredConversations.push(conversation)
}
}
)
})
return filtered
setConversations(filteredConversations)
return filteredConversations
}
const createConversation = async (userDid: string) => {
let _account = account
if (!_account) {
// Check connection and force connect
_account = await checkConnection({ autoConnect: true })
_account = await checkOrbisConnection({ autoConnect: true })
}
if (!hasLit) {
@ -222,6 +233,8 @@ function OrbisProvider({ children }: { children: ReactNode }): ReactElement {
if (data && data.length > 0) {
_did = data[0].did
} else {
_did = `did:pkh:eip155:0:${address.toLowerCase()}`
}
return _did
@ -234,7 +247,7 @@ function OrbisProvider({ children }: { children: ReactNode }): ReactElement {
useEffect(() => {
if (accountId && web3Provider) {
// Check if wallet connected
checkConnection({})
checkOrbisConnection({})
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [accountId, web3Provider])
@ -257,19 +270,16 @@ function OrbisProvider({ children }: { children: ReactNode }): ReactElement {
unreadMessages,
connectOrbis,
disconnectOrbis,
checkConnection,
checkOrbisConnection,
connectLit,
setOpenConversations,
setConversationId,
setConversations,
getConversations,
createConversation,
checkConversation,
getDid
}}
>
{children}
{account && <DirectMessages />}
<DirectMessages />
</OrbisContext.Provider>
)
}

View File

@ -1,10 +1,15 @@
.conversation {
position: relative;
height: 100%;
display: flex;
flex-direction: column;
}
.loading {
position: absolute;
top: calc(var(--spacer) / 3);
left: 50%;
transform: translateX(-50%);
padding: calc(var(--spacer) / 4);
text-align: center;
color: var(--color-secondary);

View File

@ -121,10 +121,10 @@ export default function DmConversation() {
useEffect(() => {
const el = messagesWrapper.current
messagesWrapper.current.addEventListener('scroll', onScrollMessages)
el?.addEventListener('scroll', onScrollMessages)
return () => {
el.removeEventListener('scroll', onScrollMessages)
el?.removeEventListener('scroll', onScrollMessages)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [messages])

View File

@ -1,40 +1,50 @@
.header {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
gap: calc(0.5 * var(--spacer));
align-items: center;
padding: calc(0.35 * var(--spacer)) var(--spacer);
padding: calc(0.35 * var(--spacer)) calc(0.5 * var(--spacer));
border-bottom: 1px solid var(--border-color);
box-shadow: var(--box-shadow);
font-size: var(--font-size-h5);
font-weight: var(--font-weight-bold);
cursor: pointer;
}
.icon {
margin-left: 0;
width: 1.5rem;
margin-right: calc(0.5 * var(--spacer));
fill: var(--font-color-text);
}
.back {
margin-left: 0;
width: 1rem;
margin-right: calc(0.5 * var(--spacer));
fill: var(--font-color-text);
transform: rotate(180deg);
}
.btnBack {
border: none;
background-color: transparent;
padding: 0;
margin: 0;
cursor: pointer;
width: 2rem;
height: 2rem;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.toggle {
cursor: pointer;
.btnBack:hover {
background-color: var(--background-highlight);
}
.btnBack .backIcon {
pointer-events: none;
width: 1rem;
fill: var(--font-color-text);
transform: rotate(180deg);
}
.toggleArrow {
display: flex;
align-items: center;
justify-content: center;
margin-left: auto;
background: transparent;
border: none;
@ -43,7 +53,9 @@
height: 32px;
}
.toggle .icon {
.toggleArrow .icon {
margin-left: auto;
margin-right: auto;
fill: transparent;
}

View File

@ -11,40 +11,54 @@ export default function Header() {
conversationId,
openConversations,
conversationTitle,
unreadMessages,
setOpenConversations,
setConversationId
} = useOrbis()
const handleToggle = (e: any) => {
e.preventDefault()
if (e.target.type === 'button') {
setConversationId(null)
} else {
setOpenConversations(!openConversations)
}
}
return (
<div className={styles.header}>
<div className={styles.header} onClick={handleToggle}>
{!conversationId ? (
<>
<ChatBubble role="img" aria-label="Chat" className={styles.icon} />
<div>
<ChatBubble role="img" aria-label="Chat" className={styles.icon} />
</div>
<span>Direct Messages</span>
{/* {unreadMessages.length > 0 && (
{unreadMessages.length > 0 && (
<span className={styles.notificationCount}>
{unreadMessages.length}
</span>
)} */}
)}
</>
) : (
<>
<button
type="button"
aria-label="button"
className={styles.btnBack}
onClick={() => setConversationId(null)}
>
<ArrowBack role="img" aria-label="arrow" className={styles.back} />
</button>
{openConversations && (
<button
type="button"
aria-label="button"
className={styles.btnBack}
onClick={handleToggle}
>
<ArrowBack
role="img"
aria-label="arrow"
className={styles.backIcon}
/>
</button>
)}
<span>{conversationTitle}</span>
</>
)}
<button
type="button"
className={styles.toggle}
onClick={() => setOpenConversations(!openConversations)}
>
<div className={styles.toggleArrow}>
<ChevronUp
role="img"
aria-label="Toggle"
@ -52,7 +66,7 @@ export default function Header() {
openConversations ? styles.isFlipped : ''
}`}
/>
</button>
</div>
</div>
)
}

View File

@ -1,7 +1,7 @@
.conversation {
display: flex;
align-items: center;
padding: calc(var(--spacer) / 2) var(--spacer);
padding: calc(0.5 * var(--spacer)) calc(0.5 * var(--spacer));
border-bottom: 1px solid var(--border-color);
cursor: pointer;
}

View File

@ -28,14 +28,19 @@ export default function ConversationItem({
const details = conversation.recipients_details.find(
(o) => o.did !== account.did
)
const did = conversation.recipients.find((o) => o !== account.did)
const _address = didToAddress(details?.did)
const _address = didToAddress(did)
setAddress(_address)
if (details?.metadata?.ensName) {
setName(details?.metadata?.ensName)
} else if (details?.profile?.username) {
setName(details?.profile?.username)
if (details) {
if (details?.metadata?.ensName) {
setName(details?.metadata?.ensName)
} else if (details?.profile?.username) {
setName(details?.profile?.username)
} else {
setName(accountTruncate(_address))
}
} else {
setName(accountTruncate(_address))
}

View File

@ -11,7 +11,7 @@
left: 0;
transition: transform 300ms ease 0s;
pointer-events: none;
z-index: 20;
z-index: 2;
}
.floating {
@ -40,6 +40,21 @@
overflow: hidden;
}
.walletWrapper {
margin: auto;
max-width: 320px;
text-align: center;
}
.walletWrapper p {
color: var(--color-secondary);
font-size: var(--font-size-small);
}
.walletWrapper button {
margin: var(--spacer) auto 0;
}
.isClosed {
transform: translateY(90%);
}

View File

@ -2,11 +2,79 @@ import React from 'react'
import styles from './index.module.css'
import Conversation from './Conversation'
import { useOrbis } from '@context/Orbis'
import { useWeb3 } from '@context/Web3'
import Header from './Header'
import List from './List'
import walletStyles from '../../../Header/Wallet/Account.module.css'
// import loadable from '@loadable/component'
// const Wallet = loadable(() => import('../../../Header/Wallet'))
const BodyContent = () => {
const { account, conversationId, checkOrbisConnection } = useOrbis()
const { accountId, connect } = useWeb3()
const handleActivation = async (e: React.MouseEvent) => {
e.preventDefault()
const resConnect = await connect()
if (resConnect) {
await checkOrbisConnection({ autoConnect: true, lit: true })
}
}
if (!accountId) {
return (
<div className={styles.walletWrapper}>
<div>
<h5>Connect your wallet to start messaging</h5>
<p>You will be ask to sign:</p>
<p>
Sign 1: Create your decentralized Identity (DID) to share a message
and own it
</p>
<p>Sign 2: Create your encrypted key to enable private messages</p>
<button
className={`${walletStyles.button} ${walletStyles.initial}`}
onClick={(e) => handleActivation(e)}
>
Connect <span>Wallet</span>
</button>
</div>
</div>
)
}
if (!account) {
return (
<div className={styles.walletWrapper}>
<div>
<h5>Sign your wallet to start messaging</h5>
<p>
Sign 1: Create your decentralized Identity (DID) to share a message
and own it
</p>
<p>Sign 2: Create your encrypted key to enable private messages</p>
<button
className={`${walletStyles.button} ${walletStyles.initial}`}
onClick={() =>
checkOrbisConnection({ autoConnect: true, lit: true })
}
>
Sign <span>Wallet</span>
</button>
</div>
</div>
)
}
if (conversationId) {
return <Conversation />
}
return <List />
}
export default function DirectMessages() {
const { openConversations, conversationId } = useOrbis()
const { openConversations } = useOrbis()
return (
<div
@ -17,7 +85,7 @@ export default function DirectMessages() {
<Header />
</div>
<div className={styles.bodyWrapper}>
{conversationId ? <Conversation /> : <List />}
<BodyContent />
</div>
</div>
</div>

View File

@ -19,7 +19,7 @@ export default function Details(): ReactElement {
networkId,
balance
} = useWeb3()
const { disconnectOrbis } = useOrbis()
const { checkOrbisConnection, disconnectOrbis } = useOrbis()
const { locale } = useUserPreferences()
const [mainCurrency, setMainCurrency] = useState<string>()
@ -85,6 +85,7 @@ export default function Details(): ReactElement {
onClick={async () => {
await web3Modal?.clearCachedProvider()
connect()
checkOrbisConnection({})
}}
>
Switch Wallet

View File

@ -22,25 +22,23 @@ const LinkExternal = ({ url, text }: { url: string; text: string }) => {
)
}
export default function AccountHeader({
accountId
}: {
accountId: string
}): ReactElement {
const { profile, ownAccount } = useProfile()
const { accountId: ownAccountId } = useWeb3()
const { createConversation, getDid } = useOrbis()
const [isShowMore, setIsShowMore] = useState(false)
const DmButton = ({ accountId }: { accountId: string }) => {
const { ownAccount } = useProfile()
const { accountId: ownAccountId, connect } = useWeb3()
const { checkOrbisConnection, createConversation, getDid } = useOrbis()
const [userDid, setUserDid] = useState<string | undefined>()
const toogleShowMore = () => {
setIsShowMore(!isShowMore)
const handleActivation = async (e: React.MouseEvent) => {
e.preventDefault()
const resConnect = await connect()
if (resConnect) {
await checkOrbisConnection({ autoConnect: true, lit: true })
}
}
useEffect(() => {
const getUserDid = async () => {
const did = await getDid(accountId)
console.log(did)
setUserDid(did)
}
@ -50,6 +48,44 @@ export default function AccountHeader({
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [accountId])
if (!ownAccount && userDid) {
return (
<div className={styles.dmButton}>
<Button
style="primary"
size="small"
disabled={!ownAccountId}
onClick={() => createConversation(userDid)}
>
Send Direct Message
</Button>
</div>
)
}
if (!ownAccountId) {
return (
<div className={styles.dmButton}>
<Button style="primary" size="small" onClick={handleActivation}>
Connect Wallet
</Button>
</div>
)
}
}
export default function AccountHeader({
accountId
}: {
accountId: string
}): ReactElement {
const { profile } = useProfile()
const [isShowMore, setIsShowMore] = useState(false)
const toogleShowMore = () => {
setIsShowMore(!isShowMore)
}
return (
<div className={styles.grid}>
<div>
@ -58,19 +94,7 @@ export default function AccountHeader({
</div>
<div>
{!ownAccount && userDid && (
<div className={styles.dmButton}>
<Button
style="primary"
size="small"
disabled={!ownAccountId}
onClick={() => createConversation(userDid)}
>
Send Direct Message
</Button>
{!ownAccountId && <span>Please connect your wallet</span>}
</div>
)}
<DmButton accountId={accountId} />
<Markdown text={profile?.description} className={styles.description} />
{isDescriptionTextClamped() ? (
<span className={styles.more} onClick={toogleShowMore}>