connect components to state

This commit is contained in:
Pavel Prichodko 2023-02-28 15:01:04 +01:00
parent 0ee881e2d8
commit 32a8fed0be
No known key found for this signature in database
GPG Key ID: 0EB8D75C775AB6F1
5 changed files with 51 additions and 56 deletions

View File

@ -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",

View File

@ -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}

View File

@ -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 />}

View File

@ -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>
)} )}

View File

@ -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}
/> />
) )