connect components to state
This commit is contained in:
parent
0ee881e2d8
commit
32a8fed0be
|
@ -33,7 +33,9 @@
|
||||||
"@tamagui/react-native-media-driver": "1.0.15",
|
"@tamagui/react-native-media-driver": "1.0.15",
|
||||||
"@tamagui/shorthands": "1.0.15",
|
"@tamagui/shorthands": "1.0.15",
|
||||||
"@tamagui/theme-base": "1.0.15",
|
"@tamagui/theme-base": "1.0.15",
|
||||||
"tamagui": "1.0.15"
|
"tamagui": "1.0.15",
|
||||||
|
"expo-blur": "~12.0.1",
|
||||||
|
"zustand": "^4.3.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@storybook/addon-essentials": "7.0.0-beta.21",
|
"@storybook/addon-essentials": "7.0.0-beta.21",
|
||||||
|
|
|
@ -16,15 +16,15 @@ import { Button } from '../button'
|
||||||
import { IconButton } from '../icon-button'
|
import { IconButton } from '../icon-button'
|
||||||
import { Image } from '../image'
|
import { Image } from '../image'
|
||||||
import { Input } from '../input'
|
import { Input } from '../input'
|
||||||
|
import { useChatDispatch, useChatState } from '../provider'
|
||||||
import { Reply } from '../reply'
|
import { Reply } from '../reply'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isBlurred: boolean
|
blur: boolean
|
||||||
reply: boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Composer = (props: Props) => {
|
const Composer = (props: Props) => {
|
||||||
const { isBlurred, reply } = props
|
const { blur } = props
|
||||||
|
|
||||||
const [isFocused, setIsFocused] = useState(false)
|
const [isFocused, setIsFocused] = useState(false)
|
||||||
const [text, setText] = useState('')
|
const [text, setText] = useState('')
|
||||||
|
@ -37,7 +37,10 @@ const Composer = (props: Props) => {
|
||||||
isDisabled: isImageUploadDisabled,
|
isDisabled: isImageUploadDisabled,
|
||||||
} = useImageUpload()
|
} = useImageUpload()
|
||||||
|
|
||||||
const iconButtonBlurred = isBlurred && !isFocused && imagesData.length === 0
|
const iconButtonBlurred = blur && !isFocused && imagesData.length === 0
|
||||||
|
|
||||||
|
const chatState = useChatState()
|
||||||
|
const chatDispatch = useChatDispatch()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BlurView
|
<BlurView
|
||||||
|
@ -62,15 +65,13 @@ const Composer = (props: Props) => {
|
||||||
elevation: 10,
|
elevation: 10,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{reply && (
|
{chatState?.type === 'reply' && (
|
||||||
<Stack paddingLeft={4} paddingBottom={4}>
|
<Stack paddingLeft={4} paddingBottom={4}>
|
||||||
<Reply
|
<Reply
|
||||||
type="text"
|
type="text"
|
||||||
name="Alisher"
|
name="Alisher"
|
||||||
src="https://images.unsplash.com/photo-1524638431109-93d95c968f03?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=500&ixid=MnwxfDB8MXxyYW5kb218MHx8Z2lybHx8fHx8fDE2NzM4ODQ0NzU&ixlib=rb-4.0.3&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=500"
|
src="https://images.unsplash.com/photo-1524638431109-93d95c968f03?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=500&ixid=MnwxfDB8MXxyYW5kb218MHx8Z2lybHx8fHx8fDE2NzM4ODQ0NzU&ixlib=rb-4.0.3&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=500"
|
||||||
onClose={() => {
|
onClose={() => chatDispatch({ type: 'cancel' })}
|
||||||
console.log('close')
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
)}
|
)}
|
||||||
|
@ -80,7 +81,7 @@ const Composer = (props: Props) => {
|
||||||
placeholder="Type something..."
|
placeholder="Type something..."
|
||||||
px={0}
|
px={0}
|
||||||
borderWidth={0}
|
borderWidth={0}
|
||||||
blurred={isBlurred}
|
blurred={blur}
|
||||||
onBlur={() => setIsFocused(false)}
|
onBlur={() => setIsFocused(false)}
|
||||||
onFocus={() => setIsFocused(true)}
|
onFocus={() => setIsFocused(true)}
|
||||||
onChangeText={setText}
|
onChangeText={setText}
|
||||||
|
|
|
@ -23,12 +23,12 @@ interface Props {
|
||||||
reactions: ReactionsType
|
reactions: ReactionsType
|
||||||
onOpenChange: (open: boolean) => void
|
onOpenChange: (open: boolean) => void
|
||||||
onReplyPress: VoidFunction
|
onReplyPress: VoidFunction
|
||||||
// onEditPress: VoidFunction
|
onEditPress: VoidFunction
|
||||||
// onDeletePress: VoidFunction
|
// onDeletePress: VoidFunction
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Actions = (props: Props) => {
|
export const Actions = (props: Props) => {
|
||||||
const { reactions, onOpenChange, onReplyPress } = props
|
const { reactions, onOpenChange, onReplyPress, onEditPress } = props
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => onOpenChange(false)
|
return () => onOpenChange(false)
|
||||||
|
@ -70,11 +70,7 @@ export const Actions = (props: Props) => {
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* EDIT */}
|
{/* EDIT */}
|
||||||
{/* <IconButton
|
<IconButton variant="outline" icon={<EditIcon />} onPress={onEditPress} />
|
||||||
variant="outline"
|
|
||||||
icon={<EditIcon />}
|
|
||||||
onPress={onEditPress}
|
|
||||||
/> */}
|
|
||||||
|
|
||||||
{/* DELETE */}
|
{/* DELETE */}
|
||||||
{/* <IconButton
|
{/* <IconButton
|
||||||
|
@ -90,12 +86,12 @@ export const Actions = (props: Props) => {
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
icon={<EditIcon />}
|
icon={<EditIcon />}
|
||||||
label="Edit message"
|
label="Edit message"
|
||||||
onSelect={() => console.log('edit')}
|
onSelect={onEditPress}
|
||||||
/>
|
/>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
icon={<ReplyIcon />}
|
icon={<ReplyIcon />}
|
||||||
label="Reply"
|
label="Reply"
|
||||||
onSelect={() => console.log('reply')}
|
onSelect={onReplyPress}
|
||||||
/>
|
/>
|
||||||
<DropdownMenu.Item
|
<DropdownMenu.Item
|
||||||
icon={<CopyIcon />}
|
icon={<CopyIcon />}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { Stack, Unspaced, XStack, YStack } from 'tamagui'
|
||||||
import { Author } from '../author/author'
|
import { Author } from '../author/author'
|
||||||
import { Avatar } from '../avatar'
|
import { Avatar } from '../avatar'
|
||||||
import { Image } from '../image'
|
import { Image } from '../image'
|
||||||
|
import { useChatDispatch } from '../provider'
|
||||||
import { Reply } from '../reply'
|
import { Reply } from '../reply'
|
||||||
import { Paragraph } from '../typography'
|
import { Paragraph } from '../typography'
|
||||||
import { Actions } from './components/actions'
|
import { Actions } from './components/actions'
|
||||||
|
@ -30,6 +31,8 @@ const Message = (props: Props) => {
|
||||||
const active = actionsOpen || hovered
|
const active = actionsOpen || hovered
|
||||||
// <Sheet press="long">
|
// <Sheet press="long">
|
||||||
|
|
||||||
|
const dispatch = useChatDispatch()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<YStack
|
<YStack
|
||||||
position="relative"
|
position="relative"
|
||||||
|
@ -48,9 +51,8 @@ const Message = (props: Props) => {
|
||||||
<Actions
|
<Actions
|
||||||
reactions={reactions}
|
reactions={reactions}
|
||||||
onOpenChange={setActionsOpen}
|
onOpenChange={setActionsOpen}
|
||||||
onReplyPress={() => {
|
onReplyPress={() => dispatch({ type: 'reply', messageId: '1' })}
|
||||||
console.log('reply')
|
onEditPress={() => dispatch({ type: 'edit', messageId: '1' })}
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</Unspaced>
|
</Unspaced>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -7,33 +7,32 @@ import { Avatar } from '../avatar'
|
||||||
import { Button } from '../button'
|
import { Button } from '../button'
|
||||||
import { Image } from '../image'
|
import { Image } from '../image'
|
||||||
import { Heading, Paragraph } from '../typography'
|
import { Heading, Paragraph } from '../typography'
|
||||||
import { COMMUNITIES } from './mock-data'
|
import { CHANNEL_GROUPS } from './mock-data'
|
||||||
|
|
||||||
import type { CommunityProps } from './mock-data'
|
import type { ChannelGroup } from './mock-data'
|
||||||
import type { GetProps } from '@tamagui/core'
|
|
||||||
import type { ReactNode } from 'react'
|
|
||||||
|
|
||||||
type BaseProps = GetProps<typeof Stack>
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
name: string
|
community: {
|
||||||
description: string
|
name: string
|
||||||
membersCount: number
|
description: string
|
||||||
selectedChannel?: string
|
membersCount: number
|
||||||
communities?: CommunityProps[]
|
imageUrl: string
|
||||||
onChannelPress: (channelId: string, channelIcon?: ReactNode) => void
|
}
|
||||||
} & BaseProps
|
channels?: ChannelGroup[]
|
||||||
|
selectedChannelId?: string
|
||||||
|
onChannelPress: (channelId: string) => void
|
||||||
|
}
|
||||||
|
|
||||||
const Sidebar = (props: Props) => {
|
const Sidebar = (props: Props) => {
|
||||||
const {
|
const {
|
||||||
name,
|
community,
|
||||||
description,
|
channels = CHANNEL_GROUPS,
|
||||||
membersCount,
|
selectedChannelId,
|
||||||
communities = COMMUNITIES,
|
|
||||||
selectedChannel,
|
|
||||||
onChannelPress,
|
onChannelPress,
|
||||||
} = props
|
} = props
|
||||||
|
|
||||||
|
const { name, description, membersCount, imageUrl } = community
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
backgroundColor="$background"
|
backgroundColor="$background"
|
||||||
|
@ -42,11 +41,7 @@ const Sidebar = (props: Props) => {
|
||||||
height="100%"
|
height="100%"
|
||||||
overflow="scroll"
|
overflow="scroll"
|
||||||
>
|
>
|
||||||
<Image
|
<Image src={imageUrl} width="full" aspectRatio={2.6} />
|
||||||
src="https://images.unsplash.com/photo-1574786527860-f2e274867c91?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1764&q=80"
|
|
||||||
width="full"
|
|
||||||
aspectRatio={2.6}
|
|
||||||
/>
|
|
||||||
<Stack
|
<Stack
|
||||||
paddingBottom={16}
|
paddingBottom={16}
|
||||||
marginTop={-16}
|
marginTop={-16}
|
||||||
|
@ -72,17 +67,16 @@ const Sidebar = (props: Props) => {
|
||||||
|
|
||||||
<Button>Join community</Button>
|
<Button>Join community</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
{communities.map(community => (
|
{channels.map(group => (
|
||||||
<Accordion
|
<Accordion
|
||||||
key={community.id}
|
key={group.id}
|
||||||
// This is just for the demo
|
initialExpanded={group.id === 'welcome'}
|
||||||
initialExpanded={community.id === 'welcome'}
|
title={group.title}
|
||||||
title={community.title}
|
numberOfNewMessages={group.unreadCount}
|
||||||
numberOfNewMessages={community.numberOfNewMessages}
|
|
||||||
>
|
>
|
||||||
{community.channels.map((channel, index) => {
|
{group.channels.map((channel, index) => {
|
||||||
const isLastChannelOfTheList =
|
const isLastChannelOfTheList = index === group.channels.length - 1
|
||||||
index === community.channels.length - 1
|
|
||||||
return (
|
return (
|
||||||
<AccordionItem
|
<AccordionItem
|
||||||
key={channel.id}
|
key={channel.id}
|
||||||
|
@ -90,8 +84,8 @@ const Sidebar = (props: Props) => {
|
||||||
title={channel.title}
|
title={channel.title}
|
||||||
channelStatus={channel.channelStatus}
|
channelStatus={channel.channelStatus}
|
||||||
numberOfMessages={channel.numberOfMessages}
|
numberOfMessages={channel.numberOfMessages}
|
||||||
isSelected={selectedChannel === channel.id}
|
isSelected={selectedChannelId === channel.id}
|
||||||
onPress={() => onChannelPress(channel.id, channel.icon)}
|
onPress={() => onChannelPress(channel.id)}
|
||||||
mb={isLastChannelOfTheList ? 8 : 0}
|
mb={isLastChannelOfTheList ? 8 : 0}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue