Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,10 @@ export const CustomAttachmentPickerSelectionBar = () => {
};

const styles = StyleSheet.create({
selectionBar: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16, paddingBottom: 12, },
selectionBar: {
flexDirection: 'row',
alignItems: 'center',
paddingHorizontal: 16,
paddingBottom: 12,
},
});
12 changes: 8 additions & 4 deletions package/src/components/AttachmentPicker/AttachmentPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const AttachmentPicker = () => {
AttachmentPickerContent,
attachmentPickerBottomSheetHeight,
bottomSheetRef: ref,
disableAttachmentPicker,
} = useAttachmentPickerContext();

const [currentIndex, setCurrentIndexInternal] = useState(-1);
Expand Down Expand Up @@ -89,6 +90,8 @@ export const AttachmentPicker = () => {
}
}, [currentIndex, attachmentPickerStore]);

const selectionBarRef = useRef<number | null>(null);

const initialSnapPoint = attachmentPickerBottomSheetHeight;

/**
Expand All @@ -97,7 +100,6 @@ export const AttachmentPicker = () => {
*/
const snapPoints = useMemo(() => [initialSnapPoint], [initialSnapPoint]);

const selectionBarRef = useRef<number | null>(null);
const onAttachmentPickerSelectionBarLayout = useStableCallback((e: LayoutChangeEvent) => {
selectionBarRef.current = e.nativeEvent.layout.height;
});
Expand All @@ -120,9 +122,11 @@ export const AttachmentPicker = () => {
<View onLayout={onAttachmentPickerSelectionBarLayout}>
<AttachmentPickerSelectionBar />
</View>
<AttachmentPickerContent
height={attachmentPickerBottomSheetHeight - (selectionBarRef?.current ?? 0)}
/>
{!disableAttachmentPicker ? (
<AttachmentPickerContent
height={attachmentPickerBottomSheetHeight - (selectionBarRef?.current ?? 0)}
/>
) : null}
</BottomSheet>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { Linking, Platform, Pressable, StyleSheet, Text, View } from 'react-native';

import { FlatList } from 'react-native-gesture-handler';

import { CommandSearchSource, CommandSuggestion } from 'stream-chat';

import { AttachmentMediaPicker } from './AttachmentMediaPicker/AttachmentMediaPicker';

import {
useAttachmentPickerContext,
useBottomSheetContext,
useMessageComposer,
useMessageInputContext,
useTranslationContext,
Expand All @@ -15,7 +19,6 @@ import { useAttachmentPickerState, useStableCallback } from '../../../hooks';
import { Camera, FilePickerIcon, IconProps, PollThumbnail, Recorder } from '../../../icons';
import { primitives } from '../../../theme';
import { CommandSuggestionItem } from '../../AutoCompleteInput/AutoCompleteSuggestionItem';
import { BottomSheetFlatList } from '../../BottomSheetCompatibility/BottomSheetFlatList';
import { Button } from '../../ui';

const useStyles = () => {
Expand Down Expand Up @@ -100,35 +103,65 @@ export const AttachmentPickerGenericContent = (props: AttachmentPickerGenericCon

const keyExtractor = (item: { id: string }) => item.id;

export const AttachmentCommantPickerItem = ({ item }: { item: CommandSuggestion }) => {
const messageComposer = useMessageComposer();
const { textComposer } = messageComposer;
const { inputBoxRef } = useMessageInputContext();

const AttachmentCommandPickerItemUI = ({
item,
onPress,
}: {
item: CommandSuggestion;
onPress: () => void;
}) => {
const {
theme: { semantics },
} = useTheme();

const handlePress = useCallback(() => {
textComposer.setCommand(item);
inputBoxRef.current?.focus();
}, [item, textComposer, inputBoxRef]);

return (
<Pressable
style={({ pressed }) => ({
backgroundColor: pressed ? semantics.backgroundCorePressed : undefined,
borderRadius: primitives.radiusSm,
})}
onPress={handlePress}
onPress={onPress}
>
<CommandSuggestionItem {...item} />
</Pressable>
);
};

export const AttachmentCommandNativePickerItem = ({ item }: { item: CommandSuggestion }) => {
const messageComposer = useMessageComposer();
const { textComposer } = messageComposer;
const { inputBoxRef } = useMessageInputContext();
const { close } = useBottomSheetContext();

const handlePress = useCallback(() => {
textComposer.setCommand(item);
close(() => inputBoxRef.current?.focus());
}, [textComposer, item, close, inputBoxRef]);

return <AttachmentCommandPickerItemUI item={item} onPress={handlePress} />;
};

export const AttachmentCommandPickerItem = ({ item }: { item: CommandSuggestion }) => {
const { disableAttachmentPicker } = useAttachmentPickerContext();

const messageComposer = useMessageComposer();
const { textComposer } = messageComposer;
const { inputBoxRef } = useMessageInputContext();

const handlePress = useCallback(() => {
textComposer.setCommand(item);
inputBoxRef.current?.focus();
}, [textComposer, item, inputBoxRef]);

if (disableAttachmentPicker) {
return <AttachmentCommandNativePickerItem item={item} />;
}

return <AttachmentCommandPickerItemUI item={item} onPress={handlePress} />;
};

const renderItem = ({ item }: { item: CommandSuggestion }) => {
return <AttachmentCommantPickerItem item={item} />;
return <AttachmentCommandPickerItem item={item} />;
};

const useCommandPickerStyle = () => {
Expand Down Expand Up @@ -169,7 +202,7 @@ export const AttachmentCommandPicker = () => {
return (
<>
<Text style={styles.title}>{t('Instant Commands')}</Text>
<BottomSheetFlatList
<FlatList
contentContainerStyle={styles.contentContainer}
renderItem={renderItem}
data={commands}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { useCallback } from 'react';
import React, { useCallback, useState } from 'react';

import { Platform, PressableProps, GestureResponderEvent } from 'react-native';

import { AttachmentCommandPicker } from './AttachmentPickerContent';

import {
useAttachmentPickerContext,
useChannelContext,
Expand All @@ -21,6 +23,7 @@ import {
IconProps,
} from '../../../icons';
import { Button, ButtonProps } from '../../ui';
import { BottomSheetModal } from '../../UIComponents';

export type AttachmentTypePickerButtonProps = Pick<ButtonProps, 'selected' | 'onPress'> & {
Icon: ButtonProps['LeadingIcon'];
Expand All @@ -34,12 +37,13 @@ export const AttachmentTypePickerButton = ({
onPress: onPressProp,
Icon,
}: AttachmentTypePickerButtonProps) => {
const { disableAttachmentPicker } = useAttachmentPickerContext();
const ButtonIcon = useCallback(
(props: IconProps) => Icon && <Icon {...props} width={14} height={14} />,
[Icon],
);
const onPress = useStableCallback((event: GestureResponderEvent) =>
!selected && onPressProp ? onPressProp(event) : null,
(!selected || disableAttachmentPicker) && onPressProp ? onPressProp(event) : null,
);
return (
<Button
Expand All @@ -51,18 +55,22 @@ export const AttachmentTypePickerButton = ({
size={'lg'}
variant={'secondary'}
iconOnly={true}
selected={selected}
selected={selected && !disableAttachmentPicker}
/>
);
};

export const MediaPickerButton = () => {
const { hasImagePicker } = useMessageInputContext();
const { attachmentPickerStore } = useAttachmentPickerContext();
const { hasImagePicker, pickAndUploadImageFromNativePicker } = useMessageInputContext();
const { attachmentPickerStore, disableAttachmentPicker } = useAttachmentPickerContext();
const { selectedPicker } = useAttachmentPickerState();

const setImagePicker = useStableCallback(() => {
attachmentPickerStore.setSelectedPicker('images');
if (disableAttachmentPicker) {
pickAndUploadImageFromNativePicker();
} else {
attachmentPickerStore.setSelectedPicker('images');
}
});

return hasImagePicker ? (
Expand All @@ -76,17 +84,25 @@ export const MediaPickerButton = () => {
};

export const CameraPickerButton = () => {
const { attachmentPickerStore } = useAttachmentPickerContext();
const { attachmentPickerStore, disableAttachmentPicker } = useAttachmentPickerContext();
const { selectedPicker } = useAttachmentPickerState();

const { hasCameraPicker } = useMessageInputContext();
const { hasCameraPicker, takeAndUploadImage } = useMessageInputContext();

const onCameraPickerPress = useStableCallback(() => {
attachmentPickerStore.setSelectedPicker('camera-photo');
if (disableAttachmentPicker) {
takeAndUploadImage(Platform.OS === 'android' ? 'image' : 'mixed');
} else {
attachmentPickerStore.setSelectedPicker('camera-photo');
}
});

const onVideoRecorderPickerPress = useStableCallback(() => {
attachmentPickerStore.setSelectedPicker('camera-video');
if (disableAttachmentPicker) {
takeAndUploadImage('video');
} else {
attachmentPickerStore.setSelectedPicker('camera-video');
}
});

return hasCameraPicker ? (
Expand All @@ -109,13 +125,15 @@ export const CameraPickerButton = () => {
};

export const FilePickerButton = () => {
const { attachmentPickerStore } = useAttachmentPickerContext();
const { attachmentPickerStore, disableAttachmentPicker } = useAttachmentPickerContext();
const { selectedPicker } = useAttachmentPickerState();

const { hasFilePicker, pickFile } = useMessageInputContext();

const openFilePicker = useStableCallback(() => {
attachmentPickerStore.setSelectedPicker('files');
if (!disableAttachmentPicker) {
attachmentPickerStore.setSelectedPicker('files');
}
pickFile();
});

Expand All @@ -130,7 +148,7 @@ export const FilePickerButton = () => {
};

export const PollPickerButton = () => {
const { attachmentPickerStore } = useAttachmentPickerContext();
const { attachmentPickerStore, disableAttachmentPicker } = useAttachmentPickerContext();
const { selectedPicker } = useAttachmentPickerState();

const { threadList } = useChannelContext();
Expand All @@ -140,7 +158,9 @@ export const PollPickerButton = () => {
const { openPollCreationDialog, sendMessage } = useMessageInputContext();

const openPollCreationModal = useStableCallback(() => {
attachmentPickerStore.setSelectedPicker('polls');
if (!disableAttachmentPicker) {
attachmentPickerStore.setSelectedPicker('polls');
}
openPollCreationDialog?.({ sendMessage });
});

Expand All @@ -155,20 +175,34 @@ export const PollPickerButton = () => {
};

export const CommandsPickerButton = () => {
const [showCommandsSheet, setShowCommandsSheet] = useState(false);
const { hasCommands } = useMessageInputContext();
const { attachmentPickerStore } = useAttachmentPickerContext();
const { attachmentPickerStore, disableAttachmentPicker } = useAttachmentPickerContext();
const { selectedPicker } = useAttachmentPickerState();

const setCommandsPicker = useStableCallback(() => {
attachmentPickerStore.setSelectedPicker('commands');
if (disableAttachmentPicker) {
setShowCommandsSheet(true);
} else {
attachmentPickerStore.setSelectedPicker('commands');
}
});

const onClose = useStableCallback(() => setShowCommandsSheet(false));

return hasCommands ? (
<AttachmentTypePickerButton
testID='commands-touchable'
Icon={CommandsIcon}
selected={selectedPicker === 'commands'}
onPress={setCommandsPicker}
/>
<>
<AttachmentTypePickerButton
testID='commands-touchable'
Icon={CommandsIcon}
selected={selectedPicker === 'commands'}
onPress={setCommandsPicker}
/>
{showCommandsSheet ? (
<BottomSheetModal height={338} onClose={onClose} visible={showCommandsSheet} lazy={true}>
<AttachmentCommandPicker />
</BottomSheetModal>
) : null}
</>
) : null;
};
6 changes: 3 additions & 3 deletions package/src/components/Channel/Channel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ export type ChannelPropsWithContext = Pick<ChannelContextValue, 'channel'> &

const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) => {
const {
disableAttachmentPicker = !isImageMediaLibraryAvailable(),
additionalKeyboardAvoidingViewProps,
additionalPressableProps,
additionalTextInputProps,
Expand All @@ -552,7 +553,7 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
asyncMessagesSlideToCancelDistance = 75,
AttachButton = AttachButtonDefault,
Attachment = AttachmentDefault,
attachmentPickerBottomSheetHeight = 333,
attachmentPickerBottomSheetHeight = disableAttachmentPicker ? 72 : 333,
AttachmentPickerSelectionBar = DefaultAttachmentPickerSelectionBar,
attachmentSelectionBarHeight = 72,
AudioAttachment = AudioAttachmentDefault,
Expand Down Expand Up @@ -583,7 +584,6 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
customMessageSwipeAction,
DateHeader = DateHeaderDefault,
deletedMessagesVisibilityType = 'always',
disableAttachmentPicker = !isImageMediaLibraryAvailable(),
disableKeyboardCompatibleView = false,
disableTypingIndicator,
dismissKeyboardOnMessageTouch = true,
Expand Down Expand Up @@ -2044,7 +2044,7 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
<MessageInputProvider value={inputMessageInputContext}>
<AudioPlayerProvider value={audioPlayerContext}>
<View style={{ height: '100%' }}>{children}</View>
{!disableAttachmentPicker ? <AttachmentPicker /> : null}
<AttachmentPicker />
</AudioPlayerProvider>
</MessageInputProvider>
</MessageComposerProvider>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ const useStyles = () => {
},
} = useTheme();

const { badgeBgInverse, badgeText } = semantics;
const { badgeBgInverse, textInverse } = semantics;

return useMemo(
() =>
Expand All @@ -101,11 +101,11 @@ const useStyles = () => {
durationText: {
fontSize: primitives.typographyFontSizeXxs,
fontWeight: primitives.typographyFontWeightBold,
color: badgeText,
color: textInverse,
marginLeft: primitives.spacingXxs,
...durationText,
},
}),
[badgeBgInverse, badgeText, durationContainer, durationText],
[badgeBgInverse, textInverse, durationContainer, durationText],
);
};
Loading
Loading