import React, { useMemo } from 'react'; import { Text, StyleSheet, View } from 'react-native'; import type { FlatListProps } from 'react-native'; import { Pressable } from 'react-native-gesture-handler'; import type { Channel } from 'stream-chat'; import { ChannelPreviewMutedStatus } from './ChannelPreviewMutedStatus'; import { ChannelPreviewTitle } from './ChannelPreviewTitle'; import { useIsChannelMuted } from './hooks/useIsChannelMuted'; import { useBottomSheetContext } from '../../contexts/bottomSheetContext/BottomSheetContext'; import { useComponentsContext } from '../../contexts/componentsContext/ComponentsContext'; import { useSwipeRegistryContext } from '../../contexts/swipeableContext/SwipeRegistryContext'; import { useTheme } from '../../contexts/themeContext/ThemeContext'; import { useTranslationContext } from '../../contexts/translationContext/TranslationContext'; import { useStableCallback } from '../../hooks/useStableCallback'; import { primitives } from '../../theme'; import type { ChannelActionItem } from '../ChannelList/hooks/useChannelActionItems'; import { useChannelMembersState } from '../ChannelList/hooks/useChannelMembersState'; import { useChannelMuteActive } from '../ChannelList/hooks/useChannelMuteActive'; import { useChannelOnlineMemberCount } from '../ChannelList/hooks/useChannelOnlineMemberCount'; import { useIsDirectChat } from '../ChannelList/hooks/useIsDirectChat'; import { ChannelAvatar } from '../ui/Avatar/ChannelAvatar'; import { StreamBottomSheetModalFlatList } from '../UIComponents/StreamBottomSheetModalFlatList'; export type ChannelDetailsHeaderProps = { channel: Channel }; export type ChannelDetailsBottomSheetProps = { additionalFlatListProps?: Partial>; channel: Channel; items: ChannelActionItem[]; }; export const ChannelDetailsHeader = ({ channel }: ChannelDetailsHeaderProps) => { const styles = useStyles(); const { t } = useTranslationContext(); const members = useChannelMembersState(channel); const memberCount = useMemo(() => Object.keys(members).length, [members]); const onlineCount = useChannelOnlineMemberCount(channel); const isDirectChat = useIsDirectChat(channel); const { muted: channelMuted } = useIsChannelMuted(channel); const directChatUserMuted = useChannelMuteActive(channel); const muted = isDirectChat ? directChatUserMuted : channelMuted; const displayedMemberCount = memberCount > 9 ? '9+' : `${memberCount}`; const displayedOnlineCount = onlineCount > 9 ? '9+' : `${onlineCount}`; const membersAndOnlineLabel = useMemo( () => t('{{memberCount}} members, {{onlineCount}} online', { count: memberCount, memberCount: displayedMemberCount, onlineCount: displayedOnlineCount, }), [displayedMemberCount, displayedOnlineCount, memberCount, t], ); return ( {muted ? : null} {isDirectChat ? (onlineCount === 1 ? t('Online') : t('Offline')) : membersAndOnlineLabel} ); }; export const ChannelActionItemView = ({ item }: { item: ChannelActionItem }) => { const { action, Icon, label } = item; const { close } = useBottomSheetContext(); const swipableRegistry = useSwipeRegistryContext(); const styles = useStyles(); const { theme: { semantics }, } = useTheme(); const onPress = useStableCallback(() => { action(); close(); swipableRegistry?.closeAll(); }); return ( {label} ); }; const renderChannelActionItem = ({ item }: { item: ChannelActionItem }) => ( ); const keyExtractor = (item: ChannelActionItem) => item.id; export const ChannelDetailsBottomSheet = ({ additionalFlatListProps, items, channel, }: ChannelDetailsBottomSheetProps) => { const { ChannelDetailsHeader: ChannelDetailsHeaderComponent } = useComponentsContext(); const styles = useStyles(); return ( <> ); }; const useStyles = () => { const { theme: { channelDetailsMenu: { contentContainer, header, item }, semantics, }, } = useTheme(); return useMemo( () => StyleSheet.create({ contentContainer: { flexGrow: 1, backgroundColor: semantics.backgroundCoreElevation1, ...contentContainer, }, headerContainer: { flexDirection: 'row', padding: primitives.spacingSm, gap: primitives.spacingSm, backgroundColor: 'transparent', ...header.container, }, headerMeta: { fontSize: primitives.typographyFontSizeSm, lineHeight: primitives.typographyLineHeightNormal, color: semantics.textTertiary, ...header.metaText, }, metaContainer: { gap: primitives.spacingXxs, ...header.metaContainer, }, titleContainer: { alignItems: 'center', flexDirection: 'row', gap: primitives.spacingXxs, }, itemContainer: { flexDirection: 'row', alignItems: 'center', padding: primitives.spacingSm, gap: primitives.spacingXs, ...item.container, }, itemTextStandard: { fontSize: primitives.typographyFontSizeMd, lineHeight: primitives.typographyLineHeightNormal, color: semantics.textPrimary, ...item.standardText, }, itemTextDestructive: { fontSize: primitives.typographyFontSizeMd, lineHeight: primitives.typographyLineHeightNormal, color: semantics.accentError, ...item.destructiveText, }, }), [ contentContainer, header.container, header.metaContainer, header.metaText, item.container, item.destructiveText, item.standardText, semantics.accentError, semantics.backgroundCoreElevation1, semantics.textPrimary, semantics.textTertiary, ], ); };