feat(react): implement message reactions
This commit is contained in:
parent
e31b7abff5
commit
688fd70d81
|
@ -3,63 +3,64 @@ import React from 'react'
|
||||||
import { styled } from '~/src/styles/config'
|
import { styled } from '~/src/styles/config'
|
||||||
import { Flex, Image, Popover, PopoverTrigger } from '~/src/system'
|
import { Flex, Image, Popover, PopoverTrigger } from '~/src/system'
|
||||||
|
|
||||||
|
import type { Reaction, Reactions } from '~/src/protocol/use-messages'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: React.ReactElement
|
children: React.ReactElement
|
||||||
onClick: (emoji: string) => void
|
reactions: Reactions
|
||||||
|
onClick: (reaction: Reaction) => void
|
||||||
open?: boolean
|
open?: boolean
|
||||||
onOpenChange?: (open: boolean) => void
|
onOpenChange?: (open: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const emojis: Record<Reaction, { url: string; symbol: string }> = {
|
||||||
|
heart: {
|
||||||
|
symbol: '❤️',
|
||||||
|
url: 'https://twemoji.maxcdn.com/v/latest/svg/2764.svg',
|
||||||
|
},
|
||||||
|
'thumbs-up': {
|
||||||
|
symbol: '👍️',
|
||||||
|
url: 'https://twemoji.maxcdn.com/v/latest/svg/1f44d.svg',
|
||||||
|
},
|
||||||
|
'thumbs-down': {
|
||||||
|
symbol: '👎️',
|
||||||
|
url: 'https://twemoji.maxcdn.com/v/latest/svg/1f44e.svg',
|
||||||
|
},
|
||||||
|
smile: {
|
||||||
|
symbol: '😆',
|
||||||
|
url: 'https://twemoji.maxcdn.com/v/latest/svg/1f606.svg',
|
||||||
|
},
|
||||||
|
sad: {
|
||||||
|
symbol: '😭',
|
||||||
|
url: 'https://twemoji.maxcdn.com/v/latest/svg/1f62d.svg',
|
||||||
|
},
|
||||||
|
angry: {
|
||||||
|
symbol: '😡',
|
||||||
|
url: 'https://twemoji.maxcdn.com/v/latest/svg/1f621.svg',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
export const ReactionPopover = (props: Props) => {
|
export const ReactionPopover = (props: Props) => {
|
||||||
const { children, onClick, ...popoverProps } = props
|
const { reactions, children, onClick, ...popoverProps } = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PopoverTrigger {...popoverProps}>
|
<PopoverTrigger {...popoverProps}>
|
||||||
{children}
|
{children}
|
||||||
<Popover side="top" align="center" sideOffset={6}>
|
<Popover side="top" align="center" sideOffset={6}>
|
||||||
<Flex gap={1} css={{ padding: 8 }}>
|
<Flex gap={1} css={{ padding: 8 }}>
|
||||||
<Button onClick={() => onClick('')} active={false}>
|
{Object.entries(reactions).map(([reaction, value]) => {
|
||||||
<Image
|
const emoji = emojis[reaction as Reaction]
|
||||||
width={30}
|
return (
|
||||||
src="https://twemoji.maxcdn.com/v/latest/svg/2764.svg"
|
<Button
|
||||||
alt="React with ❤️"
|
key={reaction}
|
||||||
/>
|
onClick={() => onClick(reaction as Reaction)}
|
||||||
</Button>
|
active={value.me}
|
||||||
<Button onClick={() => onClick('')} active>
|
aria-label={`React with ${emoji.symbol}`}
|
||||||
<Image
|
>
|
||||||
width={30}
|
<Image width={30} src={emoji.url} alt={emoji.symbol} />
|
||||||
src="https://twemoji.maxcdn.com/v/latest/svg/1f44d.svg"
|
|
||||||
alt="React with 👍️"
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
<Button onClick={() => onClick('')} active>
|
|
||||||
<Image
|
|
||||||
width={30}
|
|
||||||
src="https://twemoji.maxcdn.com/v/latest/svg/1f44e.svg"
|
|
||||||
alt="React with 👎️"
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
<Button onClick={() => onClick('')} active={false}>
|
|
||||||
<Image
|
|
||||||
width={30}
|
|
||||||
src="https://twemoji.maxcdn.com/v/latest/svg/1f606.svg"
|
|
||||||
alt="React with 😆"
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
<Button onClick={() => onClick('')} active={false}>
|
|
||||||
<Image
|
|
||||||
width={30}
|
|
||||||
src="https://twemoji.maxcdn.com/v/latest/svg/1f62d.svg"
|
|
||||||
alt="React with 😭"
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
<Button onClick={() => onClick('')} active={false}>
|
|
||||||
<Image
|
|
||||||
width={30}
|
|
||||||
src="https://twemoji.maxcdn.com/v/latest/svg/1f621.svg"
|
|
||||||
alt="React with 😡"
|
|
||||||
/>
|
|
||||||
</Button>
|
</Button>
|
||||||
|
)
|
||||||
|
})}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Popover>
|
</Popover>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
|
|
|
@ -1,3 +1,18 @@
|
||||||
|
export type Reaction =
|
||||||
|
| 'heart'
|
||||||
|
| 'thumbs-up'
|
||||||
|
| 'thumbs-down'
|
||||||
|
| 'smile'
|
||||||
|
| 'sad'
|
||||||
|
| 'angry'
|
||||||
|
|
||||||
|
export type Reactions = {
|
||||||
|
[key in Reaction]: {
|
||||||
|
count: number
|
||||||
|
me: boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface BaseMessage {
|
interface BaseMessage {
|
||||||
id: string
|
id: string
|
||||||
type: 'text' | 'image' | 'image-text'
|
type: 'text' | 'image' | 'image-text'
|
||||||
|
@ -9,6 +24,7 @@ interface BaseMessage {
|
||||||
pinned: boolean
|
pinned: boolean
|
||||||
mention: boolean
|
mention: boolean
|
||||||
reply?: TextReply | ImageReply | ImageTextReply
|
reply?: TextReply | ImageReply | ImageTextReply
|
||||||
|
reactions: Reactions
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TextMessage extends BaseMessage {
|
interface TextMessage extends BaseMessage {
|
||||||
|
@ -68,6 +84,14 @@ export const useMessages = (): Message[] => {
|
||||||
owner: false,
|
owner: false,
|
||||||
pinned: true,
|
pinned: true,
|
||||||
mention: false,
|
mention: false,
|
||||||
|
reactions: {
|
||||||
|
heart: { count: 0, me: false },
|
||||||
|
'thumbs-up': { count: 0, me: false },
|
||||||
|
'thumbs-down': { count: 0, me: false },
|
||||||
|
smile: { count: 0, me: false },
|
||||||
|
sad: { count: 0, me: false },
|
||||||
|
angry: { count: 0, me: false },
|
||||||
|
},
|
||||||
reply: {
|
reply: {
|
||||||
contact: {
|
contact: {
|
||||||
name: 'Leila Joyner',
|
name: 'Leila Joyner',
|
||||||
|
@ -90,6 +114,14 @@ export const useMessages = (): Message[] => {
|
||||||
owner: false,
|
owner: false,
|
||||||
pinned: false,
|
pinned: false,
|
||||||
mention: false,
|
mention: false,
|
||||||
|
reactions: {
|
||||||
|
heart: { count: 0, me: false },
|
||||||
|
'thumbs-up': { count: 0, me: false },
|
||||||
|
'thumbs-down': { count: 0, me: false },
|
||||||
|
smile: { count: 0, me: false },
|
||||||
|
sad: { count: 0, me: false },
|
||||||
|
angry: { count: 0, me: false },
|
||||||
|
},
|
||||||
reply: {
|
reply: {
|
||||||
contact: {
|
contact: {
|
||||||
name: 'Leila Joyner',
|
name: 'Leila Joyner',
|
||||||
|
@ -113,6 +145,14 @@ export const useMessages = (): Message[] => {
|
||||||
owner: false,
|
owner: false,
|
||||||
pinned: false,
|
pinned: false,
|
||||||
mention: true,
|
mention: true,
|
||||||
|
reactions: {
|
||||||
|
heart: { count: 1, me: false },
|
||||||
|
'thumbs-up': { count: 1, me: false },
|
||||||
|
'thumbs-down': { count: 3, me: true },
|
||||||
|
smile: { count: 0, me: false },
|
||||||
|
sad: { count: 0, me: false },
|
||||||
|
angry: { count: 0, me: false },
|
||||||
|
},
|
||||||
reply: {
|
reply: {
|
||||||
contact: {
|
contact: {
|
||||||
name: 'Leila Joyner',
|
name: 'Leila Joyner',
|
||||||
|
@ -137,6 +177,14 @@ export const useMessages = (): Message[] => {
|
||||||
owner: false,
|
owner: false,
|
||||||
pinned: false,
|
pinned: false,
|
||||||
mention: false,
|
mention: false,
|
||||||
|
reactions: {
|
||||||
|
heart: { count: 0, me: false },
|
||||||
|
'thumbs-up': { count: 0, me: false },
|
||||||
|
'thumbs-down': { count: 0, me: false },
|
||||||
|
smile: { count: 0, me: false },
|
||||||
|
sad: { count: 0, me: false },
|
||||||
|
angry: { count: 0, me: false },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '5',
|
id: '5',
|
||||||
|
@ -150,6 +198,14 @@ export const useMessages = (): Message[] => {
|
||||||
owner: true,
|
owner: true,
|
||||||
pinned: false,
|
pinned: false,
|
||||||
mention: false,
|
mention: false,
|
||||||
|
reactions: {
|
||||||
|
heart: { count: 0, me: false },
|
||||||
|
'thumbs-up': { count: 0, me: false },
|
||||||
|
'thumbs-down': { count: 0, me: false },
|
||||||
|
smile: { count: 0, me: false },
|
||||||
|
sad: { count: 1, me: false },
|
||||||
|
angry: { count: 1, me: true },
|
||||||
|
},
|
||||||
reply: {
|
reply: {
|
||||||
contact: {
|
contact: {
|
||||||
name: 'Leila Joyner',
|
name: 'Leila Joyner',
|
||||||
|
@ -174,6 +230,14 @@ export const useMessages = (): Message[] => {
|
||||||
owner: false,
|
owner: false,
|
||||||
pinned: false,
|
pinned: false,
|
||||||
mention: false,
|
mention: false,
|
||||||
|
reactions: {
|
||||||
|
heart: { count: 0, me: false },
|
||||||
|
'thumbs-up': { count: 10, me: true },
|
||||||
|
'thumbs-down': { count: 3, me: false },
|
||||||
|
smile: { count: 0, me: false },
|
||||||
|
sad: { count: 0, me: false },
|
||||||
|
angry: { count: 0, me: false },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '5',
|
id: '5',
|
||||||
|
@ -187,6 +251,14 @@ export const useMessages = (): Message[] => {
|
||||||
owner: true,
|
owner: true,
|
||||||
pinned: false,
|
pinned: false,
|
||||||
mention: false,
|
mention: false,
|
||||||
|
reactions: {
|
||||||
|
heart: { count: 0, me: false },
|
||||||
|
'thumbs-up': { count: 0, me: false },
|
||||||
|
'thumbs-down': { count: 0, me: false },
|
||||||
|
smile: { count: 0, me: false },
|
||||||
|
sad: { count: 0, me: false },
|
||||||
|
angry: { count: 0, me: false },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState } from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { ReactionPopover } from '~/src/components/reaction-popover'
|
import { ReactionPopover } from '~/src/components/reaction-popover'
|
||||||
import { PencilIcon } from '~/src/icons/pencil-icon'
|
import { PencilIcon } from '~/src/icons/pencil-icon'
|
||||||
|
@ -15,6 +15,8 @@ import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
} from '~/src/system'
|
} from '~/src/system'
|
||||||
|
|
||||||
|
import type { Reactions } from '~/src/protocol/use-messages'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
owner: boolean
|
owner: boolean
|
||||||
pinned: boolean
|
pinned: boolean
|
||||||
|
@ -22,6 +24,7 @@ interface Props {
|
||||||
onEditClick: () => void
|
onEditClick: () => void
|
||||||
reacting: boolean
|
reacting: boolean
|
||||||
onReactingChange: (reacting: boolean) => void
|
onReactingChange: (reacting: boolean) => void
|
||||||
|
reactions: Reactions
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Actions = (props: Props) => {
|
export const Actions = (props: Props) => {
|
||||||
|
@ -32,11 +35,13 @@ export const Actions = (props: Props) => {
|
||||||
onEditClick,
|
onEditClick,
|
||||||
reacting,
|
reacting,
|
||||||
onReactingChange,
|
onReactingChange,
|
||||||
|
reactions,
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper open={reacting}>
|
<Wrapper open={reacting}>
|
||||||
<ReactionPopover
|
<ReactionPopover
|
||||||
|
reactions={reactions}
|
||||||
open={reacting}
|
open={reacting}
|
||||||
onOpenChange={onReactingChange}
|
onOpenChange={onReactingChange}
|
||||||
onClick={emoji => {
|
onClick={emoji => {
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {
|
||||||
import { ChatInput } from '../chat-input'
|
import { ChatInput } from '../chat-input'
|
||||||
import { Actions } from './actions'
|
import { Actions } from './actions'
|
||||||
import { MessageReply } from './message-reply'
|
import { MessageReply } from './message-reply'
|
||||||
import { Reactions } from './reactions'
|
import { MessageReactions } from './reactions'
|
||||||
|
|
||||||
import type { Message } from '~/src/protocol/use-messages'
|
import type { Message } from '~/src/protocol/use-messages'
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ interface Props {
|
||||||
export const ChatMessage = (props: Props) => {
|
export const ChatMessage = (props: Props) => {
|
||||||
const { message } = props
|
const { message } = props
|
||||||
|
|
||||||
const { type, contact, owner, mention, pinned, reply } = message
|
const { type, contact, owner, mention, pinned, reply, reactions } = message
|
||||||
|
|
||||||
const [editing, setEditing] = useState(false)
|
const [editing, setEditing] = useState(false)
|
||||||
const [reacting, setReacting] = useState(false)
|
const [reacting, setReacting] = useState(false)
|
||||||
|
@ -198,7 +198,10 @@ export const ChatMessage = (props: Props) => {
|
||||||
|
|
||||||
{renderMessage()}
|
{renderMessage()}
|
||||||
|
|
||||||
<Reactions onClick={handleReaction} />
|
<MessageReactions
|
||||||
|
reactions={reactions}
|
||||||
|
onClick={handleReaction}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
|
@ -209,6 +212,7 @@ export const ChatMessage = (props: Props) => {
|
||||||
onReplyClick={handleReplyClick}
|
onReplyClick={handleReplyClick}
|
||||||
reacting={reacting}
|
reacting={reacting}
|
||||||
onReactingChange={setReacting}
|
onReactingChange={setReacting}
|
||||||
|
reactions={reactions}
|
||||||
/>
|
/>
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
<ContextMenu>
|
<ContextMenu>
|
||||||
|
|
|
@ -1,115 +1,104 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { ReactionPopover } from '~/src/components/reaction-popover'
|
import { emojis, ReactionPopover } from '~/src/components/reaction-popover'
|
||||||
import { ReactionIcon } from '~/src/icons/reaction-icon'
|
import { ReactionIcon } from '~/src/icons/reaction-icon'
|
||||||
|
import { Reaction } from '~/src/protocol/use-messages'
|
||||||
import { styled } from '~/src/styles/config'
|
import { styled } from '~/src/styles/config'
|
||||||
import { Flex, Image } from '~/src/system'
|
import { Flex, Image, Text } from '~/src/system'
|
||||||
|
|
||||||
|
import type { Reactions } from '~/src/protocol/use-messages'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onClick: (reaction: string) => void
|
reactions: Reactions
|
||||||
|
onClick: (reaction: Reaction) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Reactions = (props: Props) => {
|
export const MessageReactions = (props: Props) => {
|
||||||
const { onClick } = props
|
const { reactions, onClick } = props
|
||||||
|
|
||||||
|
const hasReaction = Object.values(reactions).some(
|
||||||
|
reaction => reaction.count !== 0
|
||||||
|
)
|
||||||
|
|
||||||
|
if (hasReaction === false) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex css={{ paddingTop: 6 }} gap={1}>
|
<Flex align="center" css={{ paddingTop: 6 }} gap={1}>
|
||||||
<Button
|
{Object.entries(reactions).map(([reaction, value]) => (
|
||||||
onClick={() => onClick('')}
|
<Reaction
|
||||||
active={false}
|
key={reaction}
|
||||||
aria-label="❤️, 1 reaction, press to react"
|
emoji={emojis[reaction as Reaction]}
|
||||||
>
|
reaction={value}
|
||||||
<Image
|
onClick={() => onClick(reaction as Reaction)}
|
||||||
width={16}
|
|
||||||
src="https://twemoji.maxcdn.com/v/latest/svg/2764.svg"
|
|
||||||
alt="❤️"
|
|
||||||
/>
|
/>
|
||||||
1
|
))}
|
||||||
</Button>
|
|
||||||
<Button
|
<ReactionPopover reactions={reactions} onClick={onClick}>
|
||||||
onClick={() => onClick('')}
|
<AddReactionButton aria-label="Add Reaction">
|
||||||
active={true}
|
<ReactionIcon width={16} height={16} />
|
||||||
aria-label="👍️, 1 reaction, press to react"
|
</AddReactionButton>
|
||||||
>
|
|
||||||
<Image
|
|
||||||
width={16}
|
|
||||||
src="https://twemoji.maxcdn.com/v/latest/svg/1f44d.svg"
|
|
||||||
alt="👍️"
|
|
||||||
/>
|
|
||||||
2
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => onClick('')}
|
|
||||||
active={true}
|
|
||||||
aria-label="👎️, 1 reaction, press to react"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
width={16}
|
|
||||||
src="https://twemoji.maxcdn.com/v/latest/svg/1f44e.svg"
|
|
||||||
alt="👎️"
|
|
||||||
/>
|
|
||||||
3
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => onClick('')}
|
|
||||||
active={false}
|
|
||||||
aria-label="😆, 1 reaction, press to react"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
width={16}
|
|
||||||
src="https://twemoji.maxcdn.com/v/latest/svg/1f606.svg"
|
|
||||||
alt="😆"
|
|
||||||
/>
|
|
||||||
1
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => onClick('')}
|
|
||||||
active={false}
|
|
||||||
aria-label="😭, 1 reaction, press to react"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
width={16}
|
|
||||||
src="https://twemoji.maxcdn.com/v/latest/svg/1f62d.svg"
|
|
||||||
alt="😭"
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => onClick('')}
|
|
||||||
active={false}
|
|
||||||
aria-label="😡, 1 reaction, press to react"
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
width={16}
|
|
||||||
src="https://twemoji.maxcdn.com/v/latest/svg/1f621.svg"
|
|
||||||
alt="😡"
|
|
||||||
/>
|
|
||||||
</Button>
|
|
||||||
<ReactionPopover
|
|
||||||
onClick={emoji => {
|
|
||||||
console.log(emoji)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button>
|
|
||||||
<ReactionIcon />
|
|
||||||
</Button>
|
|
||||||
</ReactionPopover>
|
</ReactionPopover>
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AddReactionButton = styled('button', {
|
||||||
|
color: '$gray-1',
|
||||||
|
width: 16,
|
||||||
|
height: 16,
|
||||||
|
|
||||||
|
"&[aria-expanded='true']": {
|
||||||
|
color: '$primary-1',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
interface ReactionProps {
|
||||||
|
emoji: {
|
||||||
|
url: string
|
||||||
|
symbol: string
|
||||||
|
}
|
||||||
|
reaction: Props['reactions']['smile']
|
||||||
|
onClick: VoidFunction
|
||||||
|
}
|
||||||
|
|
||||||
|
const Reaction = (props: ReactionProps) => {
|
||||||
|
const { emoji, reaction, onClick } = props
|
||||||
|
|
||||||
|
if (reaction.count === 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
onClick={onClick}
|
||||||
|
active={reaction.me}
|
||||||
|
aria-label={`${emoji.symbol}, ${reaction.count} reaction, press to react`}
|
||||||
|
>
|
||||||
|
<Image width={14} src={emoji.url} alt={emoji.symbol} />
|
||||||
|
<Text size="12">{reaction.count}</Text>
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const Button = styled('button', {
|
const Button = styled('button', {
|
||||||
padding: 2,
|
padding: '0px 8px 0px 3px',
|
||||||
boxShadow: '0px 4px 12px rgba(0, 34, 51, 0.08)',
|
boxShadow: '0px 4px 12px rgba(0, 34, 51, 0.08)',
|
||||||
background: '$accent-8',
|
background: '$accent-8',
|
||||||
borderRadius: '2px 10px 10px 10px',
|
borderRadius: '2px 10px 10px 10px',
|
||||||
minWidth: 36,
|
minWidth: 36,
|
||||||
height: 20,
|
height: 20,
|
||||||
display: 'inline-flex',
|
display: 'inline-flex',
|
||||||
|
gap: 4,
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
|
|
||||||
variants: {
|
variants: {
|
||||||
active: {
|
active: {
|
||||||
true: {},
|
true: {
|
||||||
|
border: '1px solid $primary-1',
|
||||||
|
background: '$primary-3',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import { BrowserRouter, Route, Routes } from 'react-router-dom'
|
||||||
|
|
||||||
|
import { AppProvider } from '~/src/contexts/app-context'
|
||||||
|
import { DialogProvider } from '~/src/contexts/dialog-context'
|
||||||
|
import { styled } from '~/src/styles/config'
|
||||||
|
|
||||||
|
import { MainSidebar } from '../components/main-sidebar'
|
||||||
|
import { Box } from '../system'
|
||||||
|
import { Chat } from './chat'
|
||||||
|
import { NewChat } from './new-chat'
|
||||||
|
|
||||||
|
import type { Config } from '~/src/types/config'
|
||||||
|
|
||||||
|
type Props = Config
|
||||||
|
|
||||||
|
export const Community = (props: Props) => {
|
||||||
|
const {
|
||||||
|
// theme,
|
||||||
|
// environment,
|
||||||
|
// publicKey,
|
||||||
|
router: Router = BrowserRouter,
|
||||||
|
} = props
|
||||||
|
|
||||||
|
const { options } = props
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Router>
|
||||||
|
<AppProvider config={props}>
|
||||||
|
<DialogProvider>
|
||||||
|
<Box css={{ flex: '1 0 100%' }}>
|
||||||
|
<Wrapper>
|
||||||
|
{options.enableMembers && <MainSidebar />}
|
||||||
|
<Routes>
|
||||||
|
<Route path="/:id" element={<Chat />} />
|
||||||
|
<Route path="/new" element={<NewChat />} />
|
||||||
|
</Routes>
|
||||||
|
</Wrapper>
|
||||||
|
</Box>
|
||||||
|
</DialogProvider>
|
||||||
|
</AppProvider>
|
||||||
|
</Router>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export type { Props as CommunityProps }
|
||||||
|
|
||||||
|
const Wrapper = styled('div', {
|
||||||
|
position: 'relative',
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'stretch',
|
||||||
|
})
|
Loading…
Reference in New Issue