connect UI to protocol
This commit is contained in:
parent
65d9c33bb8
commit
d0f4104b53
|
@ -1,3 +1,4 @@
|
|||
// @ts-nocheck
|
||||
import React, { useMemo, useRef, useState } from 'react'
|
||||
|
||||
import styled from 'styled-components'
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// @ts-nocheck
|
||||
import React, { useMemo, useState } from 'react'
|
||||
|
||||
import styled from 'styled-components'
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// @ts-nocheck
|
||||
import React, { useEffect, useMemo, useRef, useState } from 'react'
|
||||
|
||||
import styled from 'styled-components'
|
||||
|
|
|
@ -2,42 +2,42 @@ import React from 'react'
|
|||
|
||||
import { BellIcon } from '~/src/icons/bell-icon'
|
||||
import { ContextMenu, DropdownMenu } from '~/src/system'
|
||||
import { useAlertDialog } from '~/src/system/dialog/alert-dialog'
|
||||
import { useDialog } from '~/src/system/dialog/dialog'
|
||||
// import { useAlertDialog } from '~/src/system/dialog/alert-dialog'
|
||||
// import { useDialog } from '~/src/system/dialog/dialog'
|
||||
|
||||
import { UserProfileDialog } from '../user-profile-dialog'
|
||||
import { EditGroupChatDialog } from './edit-group-chat-dialog'
|
||||
// import { UserProfileDialog } from '../user-profile-dialog'
|
||||
// import { EditGroupChatDialog } from './edit-group-chat-dialog'
|
||||
|
||||
interface Props {
|
||||
type: 'dropdown' | 'context'
|
||||
chatType: 'channel' | 'chat' | 'group-chat'
|
||||
// chatType: 'channel' | 'chat' | 'group-chat'
|
||||
}
|
||||
|
||||
export const ChatMenu = (props: Props) => {
|
||||
const { type, chatType } = props
|
||||
const { type } = props
|
||||
|
||||
const Menu = type === 'dropdown' ? DropdownMenu : ContextMenu
|
||||
|
||||
const userProfileDialog = useDialog(UserProfileDialog)
|
||||
const editGroupChatDialog = useDialog(EditGroupChatDialog)
|
||||
// const userProfileDialog = useDialog(UserProfileDialog)
|
||||
// const editGroupChatDialog = useDialog(EditGroupChatDialog)
|
||||
|
||||
const deleteChatDialog = useAlertDialog({
|
||||
title: 'Delete Chat',
|
||||
description: 'Are you sure you want to delete this chat?',
|
||||
actionLabel: 'Delete',
|
||||
actionVariant: 'danger',
|
||||
cancelLabel: 'Keep',
|
||||
})
|
||||
const leaveGroupDialog = useAlertDialog({
|
||||
title: 'Leave Group',
|
||||
description: 'Are you sure you want to leave this group chat?',
|
||||
actionLabel: 'Leave',
|
||||
actionVariant: 'danger',
|
||||
cancelLabel: 'Stay',
|
||||
})
|
||||
// const deleteChatDialog = useAlertDialog({
|
||||
// title: 'Delete Chat',
|
||||
// description: 'Are you sure you want to delete this chat?',
|
||||
// actionLabel: 'Delete',
|
||||
// actionVariant: 'danger',
|
||||
// cancelLabel: 'Keep',
|
||||
// })
|
||||
// const leaveGroupDialog = useAlertDialog({
|
||||
// title: 'Leave Group',
|
||||
// description: 'Are you sure you want to leave this group chat?',
|
||||
// actionLabel: 'Leave',
|
||||
// actionVariant: 'danger',
|
||||
// cancelLabel: 'Stay',
|
||||
// })
|
||||
|
||||
const commonMenuItems = (
|
||||
<>
|
||||
return (
|
||||
<Menu>
|
||||
<Menu.TriggerItem label="Mute Chat" icon={<BellIcon />}>
|
||||
<Menu.Item>For 15 min</Menu.Item>
|
||||
<Menu.Item>For 1 hour</Menu.Item>
|
||||
|
@ -52,55 +52,55 @@ export const ChatMenu = (props: Props) => {
|
|||
<Menu.Item>Last 3 days</Menu.Item>
|
||||
<Menu.Item>Last 7 days</Menu.Item>
|
||||
</Menu.TriggerItem>
|
||||
</>
|
||||
)
|
||||
|
||||
if (chatType === 'channel') {
|
||||
return <Menu>{commonMenuItems}</Menu>
|
||||
}
|
||||
|
||||
if (chatType === 'group-chat') {
|
||||
return (
|
||||
<Menu>
|
||||
<Menu.Item icon={<BellIcon />}>Add / remove from group</Menu.Item>
|
||||
<Menu.Item
|
||||
icon={<BellIcon />}
|
||||
onSelect={() => editGroupChatDialog.open({})}
|
||||
>
|
||||
Edit name and image
|
||||
</Menu.Item>
|
||||
<Menu.Separator />
|
||||
{commonMenuItems}
|
||||
<Menu.Separator />
|
||||
<Menu.Item
|
||||
icon={<BellIcon />}
|
||||
danger
|
||||
onSelect={() => leaveGroupDialog.open()}
|
||||
>
|
||||
Leave Chat
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Menu>
|
||||
<Menu.Item
|
||||
icon={<BellIcon />}
|
||||
onSelect={() => userProfileDialog.open({ name: 'Satoshi' })}
|
||||
>
|
||||
View Profile
|
||||
</Menu.Item>
|
||||
<Menu.Separator />
|
||||
{commonMenuItems}
|
||||
<Menu.Separator />
|
||||
<Menu.Item
|
||||
icon={<BellIcon />}
|
||||
danger
|
||||
onSelect={() => deleteChatDialog.open()}
|
||||
>
|
||||
Delete Chat
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
)
|
||||
|
||||
// if (chatType === 'channel') {
|
||||
// return <Menu>{commonMenuItems}</Menu>
|
||||
// }
|
||||
|
||||
// if (chatType === 'group-chat') {
|
||||
// return (
|
||||
// <Menu>
|
||||
// <Menu.Item icon={<BellIcon />}>Add / remove from group</Menu.Item>
|
||||
// <Menu.Item
|
||||
// icon={<BellIcon />}
|
||||
// onSelect={() => editGroupChatDialog.open({})}
|
||||
// >
|
||||
// Edit name and image
|
||||
// </Menu.Item>
|
||||
// <Menu.Separator />
|
||||
// {commonMenuItems}
|
||||
// <Menu.Separator />
|
||||
// <Menu.Item
|
||||
// icon={<BellIcon />}
|
||||
// danger
|
||||
// onSelect={() => leaveGroupDialog.open()}
|
||||
// >
|
||||
// Leave Chat
|
||||
// </Menu.Item>
|
||||
// </Menu>
|
||||
// )
|
||||
// }
|
||||
|
||||
// return (
|
||||
// <Menu>
|
||||
// <Menu.Item
|
||||
// icon={<BellIcon />}
|
||||
// onSelect={() => userProfileDialog.open({ name: 'Satoshi' })}
|
||||
// >
|
||||
// View Profile
|
||||
// </Menu.Item>
|
||||
// <Menu.Separator />
|
||||
// {commonMenuItems}
|
||||
// <Menu.Separator />
|
||||
// <Menu.Item
|
||||
// icon={<BellIcon />}
|
||||
// danger
|
||||
// onSelect={() => deleteChatDialog.open()}
|
||||
// >
|
||||
// Delete Chat
|
||||
// </Menu.Item>
|
||||
// </Menu>
|
||||
// )
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ export const ChannelItem = (props: Props) => {
|
|||
return (
|
||||
<ContextMenuTrigger>
|
||||
<SidebarItem {...sidebarItemProps}>#{children}</SidebarItem>
|
||||
<ChatMenu type="context" chatType="channel" />
|
||||
<ChatMenu type="context" />
|
||||
</ContextMenuTrigger>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,43 +1,28 @@
|
|||
import React from 'react'
|
||||
|
||||
import { Box } from '~/src/system'
|
||||
import { useChats } from '~/src/protocol'
|
||||
import { Box } from '~/src/system'
|
||||
|
||||
import { ChannelGroup } from './channel-group'
|
||||
// import { ChannelGroup } from './channel-group'
|
||||
import { ChannelItem } from './channel-item'
|
||||
|
||||
|
||||
export const Channels = () => {
|
||||
|
||||
const chats = useChats()
|
||||
|
||||
return (
|
||||
<Box css={{padding:'8px 0'}}>
|
||||
{chats.map((chat) => (
|
||||
<Box css={{ padding: '24px 0', overflow: 'auto' }}>
|
||||
{chats.map(chat => (
|
||||
<ChannelItem
|
||||
key={chat.id}
|
||||
to={`/${chat.id}`}
|
||||
unread={false}
|
||||
muted={false}
|
||||
name={chat.identity?.displayName}
|
||||
color={chat.identity?.color}
|
||||
>
|
||||
{chat.identity!.displayName}
|
||||
</ChannelItem>
|
||||
))}
|
||||
|
||||
{/* {Object.entries(community.chats).map(([group, channels]) => (
|
||||
<ChannelGroup key={group} name={group}>
|
||||
{channels.map(channel => (
|
||||
<ChannelItem
|
||||
key={group + channel}
|
||||
to={`/${channel}`}
|
||||
unread={channel === 'general'}
|
||||
muted={channel === 'random'}
|
||||
>
|
||||
{channel}
|
||||
</ChannelItem>
|
||||
))}
|
||||
</ChannelGroup>
|
||||
))} */}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import React from 'react'
|
||||
|
||||
import { useCommunity } from '~/src/protocol'
|
||||
import { useProtocol } from '~/src/protocol'
|
||||
import { Button, CopyInput, Dialog, Flex, Grid, Text } from '~/src/system'
|
||||
|
||||
export const CommunityDialog = () => {
|
||||
const { identity, publicKey='0xTODO' } = useCommunity()
|
||||
const { displayName, description} = identity
|
||||
|
||||
const { community } = useProtocol()
|
||||
const { displayName, description } = community.identity!
|
||||
|
||||
return (
|
||||
<Dialog title={displayName}>
|
||||
|
@ -16,7 +15,7 @@ export const CommunityDialog = () => {
|
|||
<Dialog.Separator />
|
||||
<Dialog.Body>
|
||||
<Grid gap={3}>
|
||||
<CopyInput label="Community Public Key" value={publicKey} />
|
||||
<CopyInput label="Community Public Key" value="0xTODO" />
|
||||
<Text size="13" color="gray">
|
||||
To access this community, paste community public key in Status
|
||||
desktop or mobile app.
|
||||
|
@ -54,7 +53,7 @@ export const CommunityDialog = () => {
|
|||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
<Button href="https://status.im/get">Download Status for Mac</Button>
|
||||
<Button href="https://status.im/get">Download Status</Button>
|
||||
</Flex>
|
||||
</Dialog.Body>
|
||||
</Dialog>
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
import React from 'react'
|
||||
|
||||
import { useCommunity, useMembers } from '~/src/protocol'
|
||||
import { useMembers, useProtocol } from '~/src/protocol'
|
||||
import { styled } from '~/src/styles/config'
|
||||
import { Avatar, DialogTrigger, Text } from '~/src/system'
|
||||
|
||||
import { CommunityDialog } from './community-dialog'
|
||||
|
||||
export const CommunityInfo = () => {
|
||||
const community = useCommunity()
|
||||
const { community } = useProtocol()
|
||||
const members = useMembers()
|
||||
console.log("file: index.tsx > line 11 > CommunityInfo > community", community)
|
||||
|
||||
const { displayName, color } = community.identity!
|
||||
|
||||
return (
|
||||
<DialogTrigger>
|
||||
<Button>
|
||||
<Avatar size={36} />
|
||||
<Avatar size={36} name={displayName} color={color} />
|
||||
<div>
|
||||
<Text>{community.identity?.displayName}</Text>
|
||||
<Text>{displayName}</Text>
|
||||
<Text color="gray" size={12}>
|
||||
{members.length} members
|
||||
</Text>
|
||||
|
|
|
@ -19,10 +19,10 @@ export const GetStarted = () => {
|
|||
// TODO: Add skip logic
|
||||
}
|
||||
|
||||
const [account, { createAccount }] = useAccount()
|
||||
const { account, createAccount } = useAccount()
|
||||
|
||||
return (
|
||||
<Flex direction="column" align="center" gap={5}>
|
||||
<Flex direction="column" align="center" gap={5} css={{ padding: '30px 0' }}>
|
||||
<svg
|
||||
width={65}
|
||||
height={64}
|
||||
|
@ -141,22 +141,22 @@ export const GetStarted = () => {
|
|||
</defs>
|
||||
</svg>
|
||||
|
||||
<Heading align="center" size="17" weight="600">
|
||||
Want to jump into the discussion?
|
||||
</Heading>
|
||||
<Grid gap={3} align="center" justify="center">
|
||||
{/* <DialogTrigger>
|
||||
<Heading align="center" size="17" weight="600">
|
||||
Want to jump into the discussion?
|
||||
</Heading>
|
||||
<Grid gap={3} align="center" justify="center">
|
||||
{/* <DialogTrigger>
|
||||
<Button>Sync with Status profile</Button>
|
||||
<SyncStatusProfileDialog />
|
||||
</DialogTrigger> */}
|
||||
|
||||
{/* <DialogTrigger>
|
||||
{/* <DialogTrigger>
|
||||
<Button>Connect Wallet</Button>
|
||||
<ConnectWalletDialog />
|
||||
</DialogTrigger> */}
|
||||
|
||||
<Button onClick={createAccount}>Use Throwaway Profile</Button>
|
||||
{/* <DialogTrigger>
|
||||
<Button onClick={createAccount}>Use Throwaway Profile</Button>
|
||||
{/* <DialogTrigger>
|
||||
<Button>Use Throwaway Profile</Button>
|
||||
{account ? (
|
||||
<ThrowawayProfileFoundDialog onSkip={handleSkip} />
|
||||
|
@ -164,7 +164,7 @@ export const GetStarted = () => {
|
|||
<CreateProfileDialog />
|
||||
)}
|
||||
</DialogTrigger> */}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -10,22 +10,22 @@ interface Props {
|
|||
export const ThrowawayProfileFoundDialog = (props: Props) => {
|
||||
const { onSkip } = props
|
||||
|
||||
const [account] = useAccount()
|
||||
const { account } = useAccount()
|
||||
|
||||
const handleLoadThrowawayProfile = () => {
|
||||
// TODO: load throwaway profile
|
||||
}
|
||||
|
||||
if (!account) {
|
||||
return null
|
||||
}
|
||||
if (!account) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog title="Throwaway Profile Found">
|
||||
<Dialog.Body gap="5">
|
||||
<Flex direction="column" align="center" gap="2">
|
||||
<Avatar size={64} src={account.imageUrl} />
|
||||
<Heading weight="600">{account.name}</Heading>
|
||||
<Avatar size={64} />
|
||||
<Heading weight="600">{account.username}</Heading>
|
||||
<Text color="gray">
|
||||
Chatkey: 0x63FaC9201494f0bd17B9892B9fae4d52fe3BD377
|
||||
</Text>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react'
|
||||
|
||||
import { ChatMenu } from '~/src/components/chat-menu'
|
||||
import { useChannel } from '~/src/protocol'
|
||||
import { ContextMenuTrigger } from '~/src/system'
|
||||
|
||||
import { SidebarItem } from '../sidebar-item'
|
||||
|
@ -15,12 +14,10 @@ interface Props extends SidebarItemProps {
|
|||
export const ChatItem = (props: Props) => {
|
||||
const { children, ...sidebarItemProps } = props
|
||||
|
||||
const chat = useChannel(children)
|
||||
|
||||
return (
|
||||
<ContextMenuTrigger>
|
||||
<SidebarItem {...sidebarItemProps}>{children}</SidebarItem>
|
||||
<ChatMenu type="context" chatType={chat.type} />
|
||||
<ChatMenu type="context" />
|
||||
</ContextMenuTrigger>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// @ts-nocheck
|
||||
import React from 'react'
|
||||
|
||||
import { EditIcon } from '~/src/icons/edit-icon'
|
||||
|
|
|
@ -12,10 +12,12 @@ interface Props {
|
|||
muted: boolean
|
||||
unread: boolean
|
||||
children: React.ReactNode
|
||||
name?: string
|
||||
color?: string
|
||||
}
|
||||
|
||||
const SidebarItem = (props: Props, ref: Ref<HTMLAnchorElement>) => {
|
||||
const { muted, unread, children, ...buttonProps } = props
|
||||
const { muted, unread, children, name, color, ...buttonProps } = props
|
||||
|
||||
return (
|
||||
<Link
|
||||
|
@ -23,7 +25,7 @@ const SidebarItem = (props: Props, ref: Ref<HTMLAnchorElement>) => {
|
|||
state={muted ? 'muted' : unread ? 'unread' : undefined}
|
||||
{...buttonProps}
|
||||
>
|
||||
<Avatar size={24} />
|
||||
<Avatar size={24} name={name} color={color} />
|
||||
{children}
|
||||
</Link>
|
||||
)
|
||||
|
|
|
@ -1,35 +1,33 @@
|
|||
import React from 'react'
|
||||
|
||||
import { useAppState } from '~/src/contexts/app-context'
|
||||
import { useAccount } from '~/src/protocol'
|
||||
import { styled } from '~/src/styles/config'
|
||||
import { Separator } from '~/src/system'
|
||||
|
||||
import { Channels } from './components/channels'
|
||||
import { CommunityInfo } from './components/community-info'
|
||||
import { GetStarted } from './components/get-started'
|
||||
import { useAccount } from '~/src/protocol'
|
||||
// import { Messages } from './components/messages'
|
||||
|
||||
|
||||
export const MainSidebar = () => {
|
||||
const { options } = useAppState()
|
||||
const { account } = useAccount()
|
||||
|
||||
if (options.enableSidebar === false) {
|
||||
return null
|
||||
}
|
||||
|
||||
const [account] = useAccount()
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<CommunityInfo />
|
||||
<Channels />
|
||||
{/* <Separator css={{ margin: '16px 0' }} />
|
||||
<Messages /> */}
|
||||
{ !account && (
|
||||
{!account && (
|
||||
<>
|
||||
<Separator css={{ margin: '16px 0' }} />
|
||||
<GetStarted />
|
||||
<Separator />
|
||||
<GetStarted />
|
||||
</>
|
||||
)}
|
||||
</Wrapper>
|
||||
|
|
|
@ -3,25 +3,32 @@ import React from 'react'
|
|||
import { useAccount } from '~/src/protocol'
|
||||
import { Avatar, Dialog, EmojiHash, Flex, Heading, Text } from '~/src/system'
|
||||
|
||||
export const DisconnectDialog = () => {
|
||||
const [account] = useAccount()
|
||||
import type { Account } from '~/src/protocol'
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
}
|
||||
|
||||
export const DisconnectDialog = (props: Props) => {
|
||||
const { deleteAccount } = useAccount()
|
||||
const { account } = props
|
||||
|
||||
return (
|
||||
<Dialog title="Disconnect">
|
||||
<Dialog.Body gap="5">
|
||||
<Text>Do you want to disconnect your profile from this browser?</Text>
|
||||
<Flex direction="column" align="center" gap="2">
|
||||
<Avatar size={64} src={account.imageUrl} />
|
||||
<Heading weight="600">{account.name}</Heading>
|
||||
<Text color="gray">
|
||||
Chatkey: {account.chatKey}
|
||||
</Text>
|
||||
<Avatar size={64} />
|
||||
<Heading weight="600">{account.username}</Heading>
|
||||
<Text color="gray">Chatkey: {account.chatKey}</Text>
|
||||
<EmojiHash />
|
||||
</Flex>
|
||||
</Dialog.Body>
|
||||
<Dialog.Actions>
|
||||
<Dialog.Cancel>Stay Connected</Dialog.Cancel>
|
||||
<Dialog.Action variant="danger">Disconnect</Dialog.Action>
|
||||
<Dialog.Action variant="danger" onClick={deleteAccount}>
|
||||
Disconnect
|
||||
</Dialog.Action>
|
||||
</Dialog.Actions>
|
||||
</Dialog>
|
||||
)
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
import React from 'react'
|
||||
|
||||
import { useAccount, useMembers } from '~/src/protocol'
|
||||
import { styled } from '~/src/styles/config'
|
||||
import { Grid, Heading } from '~/src/system'
|
||||
|
||||
import { MemberGroup } from './member-group'
|
||||
import { MemberItem } from './member-item'
|
||||
import { UserItem } from './user-item'
|
||||
import { useMembers } from '~/src/protocol'
|
||||
|
||||
export function MemberSidebar() {
|
||||
const members = useMembers()
|
||||
const { account } = useAccount()
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
|
@ -17,9 +18,11 @@ export function MemberSidebar() {
|
|||
Members
|
||||
</Heading>
|
||||
<Grid gap="2">
|
||||
<MemberGroup label="You">
|
||||
<UserItem />
|
||||
</MemberGroup>
|
||||
{account && (
|
||||
<MemberGroup label="You">
|
||||
<UserItem account={account} />
|
||||
</MemberGroup>
|
||||
)}
|
||||
<MemberGroup label="Online">
|
||||
{members.map(member => (
|
||||
<MemberItem
|
||||
|
|
|
@ -17,10 +17,7 @@ export const MemberItem = (props: Props) => {
|
|||
|
||||
return (
|
||||
<Flex gap="2" align="center" css={{ height: 56 }}>
|
||||
<Avatar
|
||||
size={32}
|
||||
indicator={indicator}
|
||||
/>
|
||||
<Avatar size={32} indicator={indicator} />
|
||||
<div>
|
||||
<Flex align="center" gap={1}>
|
||||
<Text size="15" color="accent" truncate>
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
import React from 'react'
|
||||
|
||||
import { useAccount } from '~/src/protocol'
|
||||
import { styled } from '~/src/styles/config'
|
||||
import { Avatar, DialogTrigger, EthAddress, Flex, Text } from '~/src/system'
|
||||
|
||||
import { DisconnectDialog } from './disconnect-dialog'
|
||||
|
||||
export const UserItem = () => {
|
||||
const [account] = useAccount()
|
||||
console.log("file: user-item.tsx > line 11 > UserItem > account", account)
|
||||
import type { Account } from '~/src/protocol'
|
||||
|
||||
if (!account) {
|
||||
return null
|
||||
}
|
||||
interface Props {
|
||||
account: Account
|
||||
}
|
||||
|
||||
export const UserItem = (props: Props) => {
|
||||
const { account } = props
|
||||
|
||||
return (
|
||||
<Flex align="center" justify="between">
|
||||
<Flex gap="2" align="center" css={{ height: 56 }}>
|
||||
<Avatar size={32} src={account.imageUrl} />
|
||||
<Avatar size={32} />
|
||||
<div>
|
||||
<Flex align="center" gap={1}>
|
||||
<Text size="15" color="accent">
|
||||
{account.name}
|
||||
{account.username}
|
||||
</Text>
|
||||
</Flex>
|
||||
<EthAddress size={10} color="gray">
|
||||
|
@ -30,7 +30,6 @@ export const UserItem = () => {
|
|||
</div>
|
||||
</Flex>
|
||||
|
||||
|
||||
<DialogTrigger>
|
||||
<DisconnectButton>
|
||||
<svg
|
||||
|
@ -50,10 +49,7 @@ export const UserItem = () => {
|
|||
/>
|
||||
</svg>
|
||||
</DisconnectButton>
|
||||
{account && (
|
||||
|
||||
<DisconnectDialog />
|
||||
)}
|
||||
<DisconnectDialog account={account} />
|
||||
</DialogTrigger>
|
||||
</Flex>
|
||||
)
|
||||
|
|
|
@ -14,27 +14,27 @@ interface Props {
|
|||
}
|
||||
|
||||
export const emojis: Record<Reaction, { url: string; symbol: string }> = {
|
||||
heart: {
|
||||
LOVE: {
|
||||
symbol: '❤️',
|
||||
url: 'https://twemoji.maxcdn.com/v/latest/svg/2764.svg',
|
||||
},
|
||||
'thumbs-up': {
|
||||
THUMBS_UP: {
|
||||
symbol: '👍️',
|
||||
url: 'https://twemoji.maxcdn.com/v/latest/svg/1f44d.svg',
|
||||
},
|
||||
'thumbs-down': {
|
||||
THUMBS_DOWN: {
|
||||
symbol: '👎️',
|
||||
url: 'https://twemoji.maxcdn.com/v/latest/svg/1f44e.svg',
|
||||
},
|
||||
smile: {
|
||||
LAUGH: {
|
||||
symbol: '😆',
|
||||
url: 'https://twemoji.maxcdn.com/v/latest/svg/1f606.svg',
|
||||
},
|
||||
sad: {
|
||||
SAD: {
|
||||
symbol: '😭',
|
||||
url: 'https://twemoji.maxcdn.com/v/latest/svg/1f62d.svg',
|
||||
},
|
||||
angry: {
|
||||
ANGRY: {
|
||||
symbol: '😡',
|
||||
url: 'https://twemoji.maxcdn.com/v/latest/svg/1f621.svg',
|
||||
},
|
||||
|
|
|
@ -15,7 +15,7 @@ export const UserProfileDialog = (props: Props) => {
|
|||
<Dialog.Body align="center">
|
||||
<Avatar size="80" />
|
||||
<Heading size="22">{name}</Heading>
|
||||
<Text>Chatkey:0x63FaC9201494f0bd17B9892B9fae4d52fe3BD377</Text>
|
||||
<Text>Chatkey: 0x63FaC9201494f0bd17B9892B9fae4d52fe3BD377</Text>
|
||||
<EmojiHash />
|
||||
</Dialog.Body>
|
||||
<Dialog.Actions>
|
||||
|
|
|
@ -1,35 +1,25 @@
|
|||
import React, { useState } from 'react'
|
||||
|
||||
import { useCommunity } from '~/src/protocol/use-community'
|
||||
import { useProtocol } from '~/src/protocol'
|
||||
import { Avatar, Checkbox, Dialog, Flex, Text } from '~/src/system'
|
||||
|
||||
export const WelcomeDialog = () => {
|
||||
const { name, imageUrl, requestNeeded } = useCommunity()
|
||||
const { community } = useProtocol()
|
||||
const { identity } = community
|
||||
|
||||
const [agreed, setAgreed] = useState(false)
|
||||
|
||||
return (
|
||||
<Dialog title={`Welcome to ${name}`} size={640}>
|
||||
<Dialog title={`Welcome to ${identity?.displayName}`} size={640}>
|
||||
<Dialog.Body gap="4">
|
||||
<Flex justify="center">
|
||||
<Avatar size="64" src={imageUrl} />
|
||||
<Avatar
|
||||
size="64"
|
||||
src={identity?.displayName}
|
||||
color={identity?.color}
|
||||
/>
|
||||
</Flex>
|
||||
<Text>
|
||||
CryptoKitties sed ut perspiciatis unde omnis iste natus error sit
|
||||
voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque
|
||||
ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae
|
||||
dicta sunt explicabo.
|
||||
<br />
|
||||
<br />
|
||||
Ut enim ad minim veniam Excepteur sint occaecat cupidatat non proident
|
||||
Duis aute irure Dolore eu fugiat nulla pariatur 🚗 consectetur
|
||||
adipiscing elit.
|
||||
<br />
|
||||
<br />
|
||||
Nemo enim 😋 ipsam voluptatem quia voluptas sit aspernatur aut odit
|
||||
aut fugit, sed quia consequuntur magni dolores eos qui ratione
|
||||
voluptatem sequi nesciunt.
|
||||
</Text>
|
||||
<Text>{identity?.description}</Text>
|
||||
<Flex>
|
||||
<Checkbox checked={agreed} onChange={setAgreed}>
|
||||
I agree with the above
|
||||
|
@ -38,7 +28,8 @@ export const WelcomeDialog = () => {
|
|||
</Dialog.Body>
|
||||
<Dialog.Actions>
|
||||
<Dialog.Action disabled={agreed === false}>
|
||||
{requestNeeded ? 'Request to Join' : `Join ${name}`}
|
||||
Request to Join
|
||||
{/* {requestNeeded ? 'Request to Join' : `Join ${name}`} */}
|
||||
</Dialog.Action>
|
||||
</Dialog.Actions>
|
||||
</Dialog>
|
||||
|
|
|
@ -1,27 +1,26 @@
|
|||
import React from 'react'
|
||||
|
||||
import { useMatch } from 'react-router-dom'
|
||||
// import { PinIcon } from '~/src/icons/pin-icon'
|
||||
import { Avatar, Flex, Text } from '~/src/system'
|
||||
|
||||
import { PinIcon } from '~/src/icons/pin-icon'
|
||||
import { Avatar, DialogTrigger, Flex, Text } from '~/src/system'
|
||||
|
||||
import { PinnedMessagesDialog } from './pinned-messages-dialog'
|
||||
|
||||
import type { Channel } from '~/src/protocol'
|
||||
// import { PinnedMessagesDialog } from './pinned-messages-dialog'
|
||||
import type { Chat } from '~/src/protocol'
|
||||
|
||||
interface Props {
|
||||
chat: Channel
|
||||
chat: Chat
|
||||
}
|
||||
|
||||
export const ChatInfo = (props: Props) => {
|
||||
const { chat } = props
|
||||
console.log("file: index.tsx > line 18 > ChatInfo > chat", chat)
|
||||
|
||||
|
||||
// if (chat.type == 'channel') {
|
||||
return (
|
||||
<Flex align="center" gap="2">
|
||||
<Avatar size={36} />
|
||||
<Avatar
|
||||
size={36}
|
||||
name={chat.identity?.displayName}
|
||||
color={chat.identity?.color}
|
||||
/>
|
||||
<div>
|
||||
<Text>#{chat.identity?.displayName}</Text>
|
||||
<Flex align="center">
|
||||
|
|
|
@ -14,10 +14,11 @@ interface Props {
|
|||
mode?: 'normal' | 'editing'
|
||||
value?: string
|
||||
editing?: boolean
|
||||
onSubmit: (value: string) => void
|
||||
}
|
||||
|
||||
export const ChatInput = (props: Props) => {
|
||||
const { value, editing } = props
|
||||
const { value, editing, onSubmit } = props
|
||||
|
||||
const [inputValue, setInputValue] = useState(value ?? '')
|
||||
const { state } = useChatContext()
|
||||
|
@ -32,6 +33,13 @@ export const ChatInput = (props: Props) => {
|
|||
setInputValue(event.target.value)
|
||||
}
|
||||
|
||||
const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (event.key === 'Enter' && event.shiftKey === false) {
|
||||
onSubmit(inputValue)
|
||||
setInputValue('')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
<Box css={{ paddingBottom: 6 }}>
|
||||
|
@ -47,6 +55,7 @@ export const ChatInput = (props: Props) => {
|
|||
placeholder="Message"
|
||||
value={inputValue}
|
||||
onChange={handleChange}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
<Flex>
|
||||
<IconButton label="Pick emoji">
|
||||
|
|
|
@ -25,7 +25,7 @@ export const InputReply = (props: Props) => {
|
|||
<ReplyIcon />
|
||||
</Icon>
|
||||
<Text size="13" weight="500" truncate={false}>
|
||||
{message.contact.name}
|
||||
TODO: Add name
|
||||
</Text>
|
||||
</Flex>
|
||||
|
||||
|
@ -36,14 +36,14 @@ export const InputReply = (props: Props) => {
|
|||
<CrossIcon />
|
||||
</IconButton>
|
||||
</Flex>
|
||||
{message.type === 'text' && (
|
||||
{message.contentType === 'TEXT_PLAIN' && (
|
||||
<Flex>
|
||||
<Text size="13" truncate>
|
||||
{message.text}
|
||||
</Text>
|
||||
</Flex>
|
||||
)}
|
||||
{message.type === 'image' && (
|
||||
{message.contentType === 'IMAGE' && (
|
||||
<Image
|
||||
src={message.imageUrl}
|
||||
width={56}
|
||||
|
@ -53,23 +53,6 @@ export const InputReply = (props: Props) => {
|
|||
alt="message"
|
||||
/>
|
||||
)}
|
||||
{message.type === 'image-text' && (
|
||||
<Box>
|
||||
<Flex>
|
||||
<Text size="13" truncate>
|
||||
{message.text}
|
||||
</Text>
|
||||
</Flex>
|
||||
<Image
|
||||
src={message.imageUrl}
|
||||
width={56}
|
||||
height={56}
|
||||
fit="cover"
|
||||
radius="bubble"
|
||||
alt="message"
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
</Wrapper>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@ import React from 'react'
|
|||
|
||||
import { ReactionPopover } from '~/src/components/reaction-popover'
|
||||
import { PencilIcon } from '~/src/icons/pencil-icon'
|
||||
import { PinIcon } from '~/src/icons/pin-icon'
|
||||
// import { PinIcon } from '~/src/icons/pin-icon'
|
||||
import { ReactionIcon } from '~/src/icons/reaction-icon'
|
||||
import { ReplyIcon } from '~/src/icons/reply-icon'
|
||||
import { TrashIcon } from '~/src/icons/trash-icon'
|
||||
import { UnpinIcon } from '~/src/icons/unpin-icon'
|
||||
// import { UnpinIcon } from '~/src/icons/unpin-icon'
|
||||
import { styled } from '~/src/styles/config'
|
||||
import {
|
||||
AlertDialog,
|
||||
|
@ -15,7 +15,7 @@ import {
|
|||
Tooltip,
|
||||
} from '~/src/system'
|
||||
|
||||
import type { Reactions } from '~/src/protocol/use-messages'
|
||||
import type { Reaction, Reactions } from '~/src/protocol/use-messages'
|
||||
|
||||
interface Props {
|
||||
owner: boolean
|
||||
|
@ -23,6 +23,7 @@ interface Props {
|
|||
onReplyClick: () => void
|
||||
onEditClick: () => void
|
||||
onPinClick: () => void
|
||||
onReactionClick: (reaction: Reaction) => void
|
||||
reacting: boolean
|
||||
onReactingChange: (reacting: boolean) => void
|
||||
reactions: Reactions
|
||||
|
@ -31,10 +32,11 @@ interface Props {
|
|||
export const Actions = (props: Props) => {
|
||||
const {
|
||||
owner,
|
||||
pinned,
|
||||
// pinned,
|
||||
onReplyClick,
|
||||
onEditClick,
|
||||
onPinClick,
|
||||
// onPinClick,
|
||||
onReactionClick,
|
||||
reacting,
|
||||
onReactingChange,
|
||||
reactions,
|
||||
|
@ -47,7 +49,7 @@ export const Actions = (props: Props) => {
|
|||
open={reacting}
|
||||
onOpenChange={onReactingChange}
|
||||
onClick={emoji => {
|
||||
console.log(emoji)
|
||||
onReactionClick(emoji)
|
||||
onReactingChange(false)
|
||||
}}
|
||||
>
|
||||
|
@ -79,7 +81,7 @@ export const Actions = (props: Props) => {
|
|||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip label={pinned ? 'Unpin' : 'Pin'}>
|
||||
{/* <Tooltip label={pinned ? 'Unpin' : 'Pin'}>
|
||||
<IconButton
|
||||
label={pinned ? 'Unpin message' : 'Pin message'}
|
||||
intent="info"
|
||||
|
@ -88,7 +90,7 @@ export const Actions = (props: Props) => {
|
|||
>
|
||||
{pinned ? <UnpinIcon /> : <PinIcon />}
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Tooltip> */}
|
||||
{owner && (
|
||||
<AlertDialogTrigger>
|
||||
<Tooltip label="Delete">
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import React, { useState } from 'react'
|
||||
|
||||
import snarkdown from 'snarkdown'
|
||||
|
||||
import { UserProfileDialog } from '~/src/components/user-profile-dialog'
|
||||
import { useChatContext } from '~/src/contexts/chat-context'
|
||||
import { BellIcon } from '~/src/icons/bell-icon'
|
||||
import { PinIcon } from '~/src/icons/pin-icon'
|
||||
import { useProtocol } from '~/src/protocol/provider'
|
||||
import { styled } from '~/src/styles/config'
|
||||
import {
|
||||
Avatar,
|
||||
|
@ -25,10 +28,11 @@ import { Actions } from './actions'
|
|||
import { MessageReply } from './message-reply'
|
||||
import { MessageReactions } from './reactions'
|
||||
|
||||
import type { MessageType } from '~/src/protocol/use-messages'
|
||||
import type { Message, Reaction } from '~/src/protocol/use-messages'
|
||||
|
||||
interface Props {
|
||||
message: MessageType
|
||||
message: Message
|
||||
previousMessage?: Message
|
||||
}
|
||||
|
||||
// const MessageLink = forwardRef(function MessageLink(
|
||||
|
@ -53,15 +57,17 @@ interface Props {
|
|||
// })
|
||||
|
||||
export const ChatMessage = (props: Props) => {
|
||||
const { message } = props
|
||||
console.log("🚀 > message", message)
|
||||
const { client } = useProtocol()
|
||||
|
||||
// const { type, contact, owner, mention, pinned, reply, reactions } = message
|
||||
const owner=false
|
||||
const mention=false
|
||||
const { message } = props
|
||||
|
||||
const owner = false
|
||||
const mention = false
|
||||
const pinned = false
|
||||
const reply = false
|
||||
const { contentType, text, displayName, reactions } = message
|
||||
|
||||
const { messageId, chatId, contentType, clock, displayName, reactions } =
|
||||
message
|
||||
|
||||
const [editing, setEditing] = useState(false)
|
||||
const [reacting, setReacting] = useState(false)
|
||||
|
@ -70,26 +76,34 @@ export const ChatMessage = (props: Props) => {
|
|||
|
||||
const userProfileDialog = useDialog(UserProfileDialog)
|
||||
|
||||
const handleReplyClick = () => {
|
||||
dispatch({
|
||||
type: 'SET_REPLY',
|
||||
const handleMessageSubmit = (message: string) => {
|
||||
client.community.sendTextMessage(
|
||||
chatId,
|
||||
message,
|
||||
})
|
||||
'0x0fa999097568d1fdcc39108a08d75340bd2cee5ec59c36799007150d0a9fc896'
|
||||
)
|
||||
}
|
||||
|
||||
const handleReaction = (reaction: Reaction) => {
|
||||
client.community.sendReaction(chatId, messageId, reaction)
|
||||
}
|
||||
|
||||
const handleReplyClick = () => {
|
||||
dispatch({ type: 'SET_REPLY', message })
|
||||
}
|
||||
|
||||
const handlePinClick = () => {
|
||||
// console.log(pinned)
|
||||
}
|
||||
|
||||
const handleReaction = (reaction: string) => {
|
||||
console.log(reaction)
|
||||
// TODO: pin message
|
||||
}
|
||||
|
||||
const renderMessage = () => {
|
||||
if (editing) {
|
||||
return (
|
||||
<Box>
|
||||
<ChatInput value={message?.text ?? ''} />
|
||||
<ChatInput
|
||||
value={message?.text ?? ''}
|
||||
onSubmit={handleMessageSubmit}
|
||||
/>
|
||||
<Flex gap={2}>
|
||||
<Button
|
||||
variant="outline"
|
||||
|
@ -98,7 +112,9 @@ export const ChatMessage = (props: Props) => {
|
|||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button size="small">Save</Button>
|
||||
<Button size="small" onClick={handleMessageSubmit}>
|
||||
Save
|
||||
</Button>
|
||||
</Flex>
|
||||
</Box>
|
||||
)
|
||||
|
@ -118,37 +134,30 @@ export const ChatMessage = (props: Props) => {
|
|||
// </AlertDialogTrigger>{' '}
|
||||
return <Text>{message.text}</Text>
|
||||
}
|
||||
case 'image': {
|
||||
case 'EMOJI': {
|
||||
return (
|
||||
<Text css={{ fontSize: '3rem', lineHeight: 1.1, letterSpacing: -2 }}>
|
||||
{message.text}
|
||||
</Text>
|
||||
)
|
||||
}
|
||||
case 'IMAGE': {
|
||||
const blob = new Blob([message.image.payload], { type: 'image/jpeg' })
|
||||
|
||||
// TODO?: call URL.revokeObjectURL()
|
||||
return (
|
||||
<Flex gap={1} css={{ paddingTop: '$2' }}>
|
||||
<Image
|
||||
width={147}
|
||||
width={150}
|
||||
alt="message"
|
||||
height={196}
|
||||
src={message.imageUrl}
|
||||
height={150}
|
||||
src={URL.createObjectURL(blob)}
|
||||
radius="bubble"
|
||||
fit="cover"
|
||||
/>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
case 'image-text': {
|
||||
const { text, imageUrl } = message
|
||||
|
||||
return (
|
||||
<>
|
||||
<Text>{text}</Text>
|
||||
<Flex gap={1} css={{ paddingTop: '$1' }}>
|
||||
<Image
|
||||
width={147}
|
||||
alt="message"
|
||||
height={196}
|
||||
src={imageUrl}
|
||||
radius="bubble"
|
||||
/>
|
||||
</Flex>
|
||||
</>
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -161,12 +170,11 @@ export const ChatMessage = (props: Props) => {
|
|||
<Box>
|
||||
<DropdownMenuTrigger>
|
||||
<button type="button">
|
||||
{/* <Avatar size={44} src={contact.imageUrl} /> */}
|
||||
<Avatar size={44} />
|
||||
</button>
|
||||
<DropdownMenu>
|
||||
<Flex direction="column" align="center" gap="1">
|
||||
{/* <Avatar size="36" src={contact.imageUrl} /> */}
|
||||
{/* <Text>{contact.name}</Text> */}
|
||||
<Avatar size="36" />
|
||||
<Text>{displayName}</Text>
|
||||
<EmojiHash />
|
||||
</Flex>
|
||||
|
@ -197,20 +205,22 @@ export const ChatMessage = (props: Props) => {
|
|||
</Box>
|
||||
|
||||
<Box css={{ flex: 1 }}>
|
||||
{pinned && (
|
||||
{/* {pinned && (
|
||||
<Flex gap={1}>
|
||||
<PinIcon width={8} />
|
||||
<Text size="13">Pinned by carmen.eth</Text>
|
||||
<Text size="13">Pinned by {contact.name}</Text>
|
||||
</Flex>
|
||||
)}
|
||||
)} */}
|
||||
|
||||
<Flex gap="1" align="center">
|
||||
<Text color="primary" weight="500" size="15">
|
||||
{displayName}
|
||||
{/* {contact.name} */}
|
||||
</Text>
|
||||
<Text size="10" color="gray">
|
||||
10:00 AM
|
||||
{new Date(Number(clock)).toLocaleTimeString([], {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
})}
|
||||
</Text>
|
||||
</Flex>
|
||||
|
||||
|
@ -229,6 +239,7 @@ export const ChatMessage = (props: Props) => {
|
|||
onEditClick={() => setEditing(true)}
|
||||
onReplyClick={handleReplyClick}
|
||||
onPinClick={handlePinClick}
|
||||
onReactionClick={handleReaction}
|
||||
reacting={reacting}
|
||||
onReactingChange={setReacting}
|
||||
reactions={reactions}
|
||||
|
@ -236,7 +247,7 @@ export const ChatMessage = (props: Props) => {
|
|||
</Wrapper>
|
||||
<ContextMenu>
|
||||
<ContextMenu.Item onSelect={handleReplyClick}>Reply</ContextMenu.Item>
|
||||
<ContextMenu.Item onSelect={handlePinClick}>Pin</ContextMenu.Item>
|
||||
{/* <ContextMenu.Item onSelect={handlePinClick}>Pin</ContextMenu.Item> */}
|
||||
</ContextMenu>
|
||||
</ContextMenuTrigger>
|
||||
</>
|
||||
|
|
|
@ -7,7 +7,7 @@ import { useAppState } from '~/src/contexts/app-context'
|
|||
import { BellIcon } from '~/src/icons/bell-icon'
|
||||
import { DotsIcon } from '~/src/icons/dots-icon'
|
||||
import { GroupIcon } from '~/src/icons/group-icon'
|
||||
import { useChannel } from '~/src/protocol'
|
||||
import { useChat } from '~/src/protocol'
|
||||
import { styled } from '~/src/styles/config'
|
||||
import { DropdownMenuTrigger, Flex, IconButton, Separator } from '~/src/system'
|
||||
|
||||
|
@ -23,7 +23,7 @@ export const Navbar = (props: Props) => {
|
|||
const { state, dispatch } = useAppState()
|
||||
const { params } = useMatch(':id')! // eslint-disable-line @typescript-eslint/no-non-null-assertion
|
||||
|
||||
const chat = useChannel(params.id!)
|
||||
const chat = useChat(params.id!)
|
||||
|
||||
return (
|
||||
<NavbarWrapper>
|
||||
|
@ -44,7 +44,7 @@ export const Navbar = (props: Props) => {
|
|||
<IconButton label="Options">
|
||||
<DotsIcon />
|
||||
</IconButton>
|
||||
<ChatMenu type="dropdown" chatType="channel" />
|
||||
<ChatMenu type="dropdown" />
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<Separator orientation="vertical" css={{ height: 24 }} />
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// TODO: handle non-existing chat ID
|
||||
|
||||
import React, { useEffect, useRef } from 'react'
|
||||
|
||||
import { useMatch } from 'react-router-dom'
|
||||
|
@ -5,7 +7,8 @@ import { useMatch } from 'react-router-dom'
|
|||
import { MemberSidebar } from '~/src/components/member-sidebar'
|
||||
import { useAppState } from '~/src/contexts/app-context'
|
||||
import { ChatProvider } from '~/src/contexts/chat-context'
|
||||
import { useChannel } from '~/src/protocol'
|
||||
import { useChat } from '~/src/protocol'
|
||||
import { useProtocol } from '~/src/protocol/provider'
|
||||
import { useMessages } from '~/src/protocol/use-messages'
|
||||
import { styled } from '~/src/styles/config'
|
||||
import { Avatar, Flex, Heading, Text } from '~/src/system'
|
||||
|
@ -14,59 +17,85 @@ import { ChatInput } from './components/chat-input'
|
|||
import { ChatMessage } from './components/chat-message'
|
||||
import { Navbar } from './components/navbar'
|
||||
|
||||
const ChatStart = () => {
|
||||
// TODO: unify this with the useChat hook
|
||||
const { params } = useMatch(':id')! // eslint-disable-line @typescript-eslint/no-non-null-assertion
|
||||
interface ChatStartProps {
|
||||
chatId: string
|
||||
}
|
||||
|
||||
const chat = useChannel(params.id!)
|
||||
const ChatStart = (props: ChatStartProps) => {
|
||||
const { chatId } = props
|
||||
|
||||
const { identity } = useChat(chatId)
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="3" align="center" css={{ marginBottom: 50 }}>
|
||||
{/* <Avatar size={120} src={chat.imageUrl} /> */}
|
||||
<Heading>{chat.identity?.displayName}</Heading>
|
||||
<Avatar size={120} name={identity?.displayName} color={identity?.color} />
|
||||
<Heading>{identity?.displayName}</Heading>
|
||||
<Text>
|
||||
Welcome to the beginning of the #{chat.identity?.displayName} channel!
|
||||
Welcome to the beginning of the #{identity?.displayName} channel!
|
||||
</Text>
|
||||
</Flex>
|
||||
)
|
||||
}
|
||||
|
||||
const Content = () => {
|
||||
const contentRef = useRef<HTMLDivElement>(null)
|
||||
interface ContentProps {
|
||||
chatId: string
|
||||
}
|
||||
|
||||
const { params } = useMatch(':id')! // eslint-disable-line @typescript-eslint/no-non-null-assertion
|
||||
const Content = (props: ContentProps) => {
|
||||
const { chatId } = props
|
||||
|
||||
const contentRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
contentRef.current!.scrollTop = contentRef.current!.scrollHeight ?? 0
|
||||
}, [])
|
||||
}, [chatId])
|
||||
|
||||
const messages = useMessages(params.id!)
|
||||
const messages = useMessages(chatId)
|
||||
|
||||
return (
|
||||
<ContentWrapper ref={contentRef}>
|
||||
<ChatStart />
|
||||
{messages.data.map(message => (
|
||||
<ChatMessage key={message.messageId} message={message} />
|
||||
{/* <Button onClick={messages.fetchMore}>Fetch more</Button> */}
|
||||
<ChatStart chatId={chatId} />
|
||||
{messages.data.map((message, index) => (
|
||||
<ChatMessage
|
||||
key={message.messageId}
|
||||
message={message}
|
||||
previousMessage={messages.data[index - 1]}
|
||||
/>
|
||||
))}
|
||||
</ContentWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export const Chat = () => {
|
||||
const { client } = useProtocol()
|
||||
const { state, options } = useAppState()
|
||||
|
||||
const { params } = useMatch(':id')! // eslint-disable-line @typescript-eslint/no-non-null-assertion
|
||||
const chatId = params.id!
|
||||
|
||||
const chat = useChat(chatId)
|
||||
|
||||
// TODO: Update condition based on a chat type
|
||||
const enableMembers = options.enableMembers // && (chat.type === 'group' || chat.type === 'channel')
|
||||
const enableMembers = options.enableMembers ?? false // && (chat.type === 'group' || chat.type === 'channel')
|
||||
const showMembers = enableMembers && state.showMembers
|
||||
|
||||
const handleMessageSubmit = (message: string) => {
|
||||
client.community.sendTextMessage(
|
||||
chatId,
|
||||
message
|
||||
// '0x0fa999097568d1fdcc39108a08d75340bd2cee5ec59c36799007150d0a9fc896'
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<ChatProvider>
|
||||
<Wrapper>
|
||||
<Main>
|
||||
<Navbar enableMembers={enableMembers} />
|
||||
<Content />
|
||||
<ChatInput />
|
||||
<Content chatId={chatId} />
|
||||
<ChatInput onSubmit={handleMessageSubmit} />
|
||||
</Main>
|
||||
{showMembers && <MemberSidebar />}
|
||||
</Wrapper>
|
||||
|
|
Loading…
Reference in New Issue