diff --git a/examples/SampleApp/src/components/BottomTabs.tsx b/examples/SampleApp/src/components/BottomTabs.tsx index 684a1ea694..197899782c 100644 --- a/examples/SampleApp/src/components/BottomTabs.tsx +++ b/examples/SampleApp/src/components/BottomTabs.tsx @@ -27,7 +27,6 @@ const styles = StyleSheet.create({ paddingVertical: 8, }, tabListContainer: { - borderTopColor: 'rgba(0, 0, 0, 0.0677)', borderTopWidth: 1, flexDirection: 'row', }, @@ -128,8 +127,9 @@ const Tab = (props: TabProps) => { export const BottomTabs: React.FC = (props) => { const { navigation, state } = props; - useTheme(); - const { white } = useLegacyColors(); + const { + theme: { semantics }, + } = useTheme(); const { bottom } = useSafeAreaInsets(); return ( @@ -137,7 +137,8 @@ export const BottomTabs: React.FC = (props) => { style={[ styles.tabListContainer, { - backgroundColor: white, + backgroundColor: semantics.backgroundCoreElevation1, + borderTopColor: semantics.borderCoreSubtle, paddingBottom: bottom, }, ]} diff --git a/package/src/components/Attachment/Attachment.tsx b/package/src/components/Attachment/Attachment.tsx index 8232065edc..3ea96757ba 100644 --- a/package/src/components/Attachment/Attachment.tsx +++ b/package/src/components/Attachment/Attachment.tsx @@ -219,9 +219,14 @@ const useAudioAttachmentStyles = () => { const { theme: { semantics }, } = useTheme(); - const { isMyMessage, messageHasOnlySingleAttachment } = useMessageContext(); - - const showBackgroundTransparent = messageHasOnlySingleAttachment; + const { isMyMessage, message, messageHasOnlySingleAttachment } = useMessageContext(); + + const messageHasSingleAttachment = message.attachments?.length === 1; + const messageHasCaption = !!message.text?.trim(); + const messageIsQuotedReply = !!(message.quoted_message || message.quoted_message_id); + const showBackgroundTransparent = + messageHasOnlySingleAttachment || + (messageIsQuotedReply && messageHasSingleAttachment && !messageHasCaption); return useMemo(() => { return StyleSheet.create({ diff --git a/package/src/components/Attachment/__tests__/Attachment.test.tsx b/package/src/components/Attachment/__tests__/Attachment.test.tsx index ba8869acac..d4d1c88ae4 100644 --- a/package/src/components/Attachment/__tests__/Attachment.test.tsx +++ b/package/src/components/Attachment/__tests__/Attachment.test.tsx @@ -11,7 +11,7 @@ import type { MessageContextValue } from '../../../contexts/messageContext/Messa import { MessageProvider } from '../../../contexts/messageContext/MessageContext'; import type { MessagesContextValue } from '../../../contexts/messagesContext/MessagesContext'; import { MessagesProvider } from '../../../contexts/messagesContext/MessagesContext'; -import { ThemeProvider } from '../../../contexts/themeContext/ThemeContext'; +import { mergeThemes, ThemeProvider } from '../../../contexts/themeContext/ThemeContext'; import { generateAudioAttachment, generateFileAttachment, @@ -19,6 +19,7 @@ import { generateVideoAttachment, } from '../../../mock-builders/generator/attachment'; import { generateMessage } from '../../../mock-builders/generator/message'; +import { FileTypes } from '../../../types/types'; import { ImageLoadingFailedIndicator } from '../../Attachment/ImageLoadingFailedIndicator'; import { ImageLoadingIndicator } from '../../Attachment/ImageLoadingIndicator'; @@ -48,8 +49,11 @@ jest.mock('../../../hooks/usePendingAttachmentUpload', () => ({ })), })); -const getAttachmentComponent = (props: ComponentProps) => { - const message = generateMessage(); +const getAttachmentComponent = ( + props: ComponentProps, + messageContextValue: Partial = {}, +) => { + const message = messageContextValue.message ?? generateMessage(); return ( @@ -63,7 +67,9 @@ const getAttachmentComponent = (props: ComponentProps) => { } as unknown as MessagesContextValue } > - + @@ -79,6 +85,8 @@ const getWaveformBarCount = (root: ReactTestInstance) => }).length; describe('Attachment', () => { + const lightTheme = mergeThemes({ scheme: 'light' }); + it('should render File component for "audio" type attachment', async () => { const attachment = generateAudioAttachment(); const { getByTestId } = render(getAttachmentComponent({ attachment })); @@ -122,6 +130,94 @@ describe('Attachment', () => { isSoundPackageAvailable.mockReturnValue(false); }); + it('uses a transparent audio player background for quoted replies without captions', async () => { + const { isSoundPackageAvailable } = require('../../../native'); + isSoundPackageAvailable.mockReturnValue(true); + const attachment = generateAudioAttachment({ + duration: 10, + waveform_data: [0.2, 0.6, 0.4], + }); + const quotedMessage = generateMessage(); + const message = generateMessage({ + attachments: [attachment], + quoted_message: quotedMessage, + quoted_message_id: quotedMessage.id, + text: '', + }); + + const { getByLabelText } = render( + getAttachmentComponent( + { attachment }, + { isMyMessage: false, message, messageHasOnlySingleAttachment: false }, + ), + ); + + await waitFor(() => { + const style = StyleSheet.flatten(getByLabelText('audio-attachment-preview').props.style); + expect(style.backgroundColor).toBe('transparent'); + }); + isSoundPackageAvailable.mockReturnValue(false); + }); + + it('keeps the audio player background for quoted replies with captions', async () => { + const { isSoundPackageAvailable } = require('../../../native'); + isSoundPackageAvailable.mockReturnValue(true); + const attachment = generateAudioAttachment({ + duration: 10, + type: FileTypes.VoiceRecording, + waveform_data: [0.2, 0.6, 0.4], + }); + const quotedMessage = generateMessage(); + const message = generateMessage({ + attachments: [attachment], + quoted_message: quotedMessage, + quoted_message_id: quotedMessage.id, + text: 'caption', + }); + + const { getByLabelText } = render( + getAttachmentComponent( + { attachment }, + { isMyMessage: false, message, messageHasOnlySingleAttachment: false }, + ), + ); + + await waitFor(() => { + const style = StyleSheet.flatten(getByLabelText('audio-attachment-preview').props.style); + expect(style.backgroundColor).toBe(lightTheme.semantics.chatBgAttachmentIncoming); + }); + isSoundPackageAvailable.mockReturnValue(false); + }); + + it('keeps the audio player background for quoted replies with multiple attachments and no captions', async () => { + const { isSoundPackageAvailable } = require('../../../native'); + isSoundPackageAvailable.mockReturnValue(true); + const attachment = generateAudioAttachment({ + duration: 10, + waveform_data: [0.2, 0.6, 0.4], + }); + const quotedMessage = generateMessage(); + const message = generateMessage({ + attachments: [attachment, generateAudioAttachment()], + quoted_message: quotedMessage, + quoted_message_id: quotedMessage.id, + text: '', + }); + + const { getByLabelText } = render( + getAttachmentComponent( + { attachment }, + { isMyMessage: false, message, messageHasOnlySingleAttachment: false }, + ), + ); + + await waitFor(() => { + const style = StyleSheet.flatten(getByLabelText('audio-attachment-preview').props.style); + expect(style.backgroundColor).toBe(lightTheme.semantics.chatBgAttachmentIncoming); + }); + isSoundPackageAvailable.mockReturnValue(false); + }); + it('should render UrlPreview component if attachment has title_link or og_scrape_url', async () => { const attachment = generateImageAttachment({ og_scrape_url: uuidv4(), diff --git a/package/src/components/ImageGallery/components/ImageGalleryFooter.tsx b/package/src/components/ImageGallery/components/ImageGalleryFooter.tsx index bbd37cf0e8..5f645d4978 100644 --- a/package/src/components/ImageGallery/components/ImageGalleryFooter.tsx +++ b/package/src/components/ImageGallery/components/ImageGalleryFooter.tsx @@ -200,7 +200,7 @@ const useStyles = () => { container: { backgroundColor: semantics.backgroundCoreElevation1, borderTopWidth: 1, - borderTopColor: semantics.borderCoreDefault, + borderTopColor: semantics.borderCoreSubtle, ...footer.container, }, centerContainer: { diff --git a/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx b/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx index 1778c71750..a3dd6b8cbc 100644 --- a/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx +++ b/package/src/components/ImageGallery/components/ImageGalleryHeader.tsx @@ -131,7 +131,7 @@ const useStyles = () => { flexDirection: 'row', justifyContent: 'space-between', borderBottomWidth: 1, - borderBottomColor: semantics.borderCoreDefault, + borderBottomColor: semantics.borderCoreSubtle, ...header.innerContainer, }, rightContainer: { diff --git a/package/src/components/Message/MessageItemView/MessageFooter.tsx b/package/src/components/Message/MessageItemView/MessageFooter.tsx index 779f553e1f..c9b4653aaa 100644 --- a/package/src/components/Message/MessageItemView/MessageFooter.tsx +++ b/package/src/components/Message/MessageItemView/MessageFooter.tsx @@ -198,7 +198,7 @@ const useStyles = () => { flexDirection: 'row', justifyContent: 'center', paddingVertical: primitives.spacingXxs, - gap: primitives.spacingXs, + gap: primitives.spacingXxs, }, name: { flexShrink: 1, diff --git a/package/src/components/MessageInput/MessageComposer.tsx b/package/src/components/MessageInput/MessageComposer.tsx index d8b3d16171..4e74adab7f 100644 --- a/package/src/components/MessageInput/MessageComposer.tsx +++ b/package/src/components/MessageInput/MessageComposer.tsx @@ -376,7 +376,7 @@ const MessageComposerWithContext = (props: MessageComposerPropsWithContext) => { { borderTopWidth: 1, backgroundColor: semantics.backgroundCoreElevation1, - borderColor: semantics.borderCoreDefault, + borderTopColor: semantics.borderCoreSubtle, // paddingBottom: BOTTOM_OFFSET, paddingBottom: selectedPicker && !isKeyboardVisible diff --git a/package/src/components/MessageInput/SendMessageDisallowedIndicator.tsx b/package/src/components/MessageInput/SendMessageDisallowedIndicator.tsx index e32ff582ff..5a95f877e5 100644 --- a/package/src/components/MessageInput/SendMessageDisallowedIndicator.tsx +++ b/package/src/components/MessageInput/SendMessageDisallowedIndicator.tsx @@ -30,7 +30,7 @@ const useStyles = () => { return StyleSheet.create({ container: { backgroundColor: semantics.backgroundCoreApp, - borderTopColor: semantics.borderCoreDefault, + borderTopColor: semantics.borderCoreSubtle, height: 48, ...container, }, diff --git a/package/src/components/MessageList/__tests__/__snapshots__/TypingIndicator.test.tsx.snap b/package/src/components/MessageList/__tests__/__snapshots__/TypingIndicator.test.tsx.snap index cd955f96fe..77cbf9e71d 100644 --- a/package/src/components/MessageList/__tests__/__snapshots__/TypingIndicator.test.tsx.snap +++ b/package/src/components/MessageList/__tests__/__snapshots__/TypingIndicator.test.tsx.snap @@ -81,7 +81,11 @@ exports[`TypingIndicator should match typing indicator snapshot 1`] = ` "borderColor": "rgba(26, 27, 37, 0.1)", "borderWidth": 1, }, - undefined, + { + "borderColor": "#ffffff", + "borderRadius": 9999, + "borderWidth": 2, + }, ] } testID="avatar-image" @@ -143,7 +147,11 @@ exports[`TypingIndicator should match typing indicator snapshot 1`] = ` "borderColor": "rgba(26, 27, 37, 0.1)", "borderWidth": 1, }, - undefined, + { + "borderColor": "#ffffff", + "borderRadius": 9999, + "borderWidth": 2, + }, ] } testID="avatar-image" diff --git a/package/src/components/Poll/components/CreatePollHeader.tsx b/package/src/components/Poll/components/CreatePollHeader.tsx index 2877ad668f..33c91a4e5e 100644 --- a/package/src/components/Poll/components/CreatePollHeader.tsx +++ b/package/src/components/Poll/components/CreatePollHeader.tsx @@ -4,7 +4,7 @@ import { StyleSheet, Text, View } from 'react-native'; import { useTheme } from '../../../contexts/themeContext/ThemeContext'; import { useTranslationContext } from '../../../contexts/translationContext/TranslationContext'; import { Check, IconProps } from '../../../icons'; -import { Cross } from '../../../icons/xmark-1'; +import { ArrowLeft } from '../../../icons/arrow-left'; import { primitives } from '../../../theme'; import { Button } from '../../ui'; import { useCanCreatePoll } from '../hooks/useCanCreatePoll'; @@ -54,8 +54,9 @@ export const CreatePollHeader = ({ accessibilityLabelKey='a11y/Close poll creation' variant='secondary' onPress={onBackPressHandler} - type='solid' - LeadingIcon={Cross} + type='ghost' + size='md' + LeadingIcon={ArrowLeft} iconOnly /> diff --git a/package/src/components/Poll/components/PollModalHeader.tsx b/package/src/components/Poll/components/PollModalHeader.tsx index 85a07b78ec..ed4d57e54a 100644 --- a/package/src/components/Poll/components/PollModalHeader.tsx +++ b/package/src/components/Poll/components/PollModalHeader.tsx @@ -2,7 +2,7 @@ import React, { useMemo } from 'react'; import { StyleSheet, Text, View } from 'react-native'; import { useTheme } from '../../../contexts'; -import { Cross } from '../../../icons/xmark-1'; +import { ArrowLeft } from '../../../icons/arrow-left'; import { primitives } from '../../../theme'; import { Button } from '../../ui'; @@ -27,10 +27,10 @@ export const PollModalHeader = ({ onPress, title }: PollModalHeaderProps) => {