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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ index.android.bundle
*.DSYM.zip
**/metrics/
package/shared-native/.sync-state/

.claude/worktrees
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
[![NPM](https://img.shields.io/npm/v/stream-chat-react-native.svg)](https://www.npmjs.com/package/stream-chat-react-native)
[![Build Status](https://github.com/GetStream/stream-chat-react-native/actions/workflows/release.yml/badge.svg)](https://github.com/GetStream/stream-chat-react-native/actions)
[![Component Reference](https://img.shields.io/badge/docs-component%20reference-blue.svg)](https://getstream.io/chat/docs/sdk/reactnative)
![JS Bundle Size](https://img.shields.io/badge/js_bundle_size-360%20KB-blue)
![JS Bundle Size](https://img.shields.io/badge/js_bundle_size-368%20KB-blue)

<img align="right" src="https://getstream.imgix.net/images/ios-chat-tutorial/iphone_chat_art@3x.png?auto=format,enhance" width="50%" />

Expand Down
1 change: 1 addition & 0 deletions examples/ExpoMessaging/app/channel/[cid]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export default function ChannelScreen() {
channel={channel}
onPressMessage={onPressMessage}
keyboardVerticalOffset={headerHeight}
topInset={headerHeight}
thread={thread}
>
<MessageList
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export default function ThreadScreen() {
audioRecordingEnabled={true}
channel={channel}
keyboardVerticalOffset={Platform.OS === 'ios' ? headerHeight : undefined}
topInset={headerHeight}
thread={thread}
threadList
>
Expand Down
3 changes: 2 additions & 1 deletion examples/ExpoMessaging/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,14 @@
"react-dom": "19.2.0",
"react-native": "0.83.2",
"react-native-gesture-handler": "~2.30.0",
"react-native-keyboard-controller": "1.20.7",
"react-native-maps": "1.26.20",
"react-native-reanimated": "4.2.1",
"react-native-safe-area-context": "~5.6.2",
"react-native-screens": "~4.23.0",
"react-native-svg": "15.15.3",
"react-native-web": "^0.21.0",
"react-native-teleport": "^1.0.2",
"react-native-web": "^0.21.0",
"react-native-worklets": "0.7.2",
"stream-chat-expo": "link:../../package/expo-package",
"stream-chat-react-native-core": "link:../../package"
Expand Down
15 changes: 11 additions & 4 deletions examples/ExpoMessaging/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5526,6 +5526,13 @@ react-native-is-edge-to-edge@1.2.1, react-native-is-edge-to-edge@^1.2.1:
resolved "https://registry.yarnpkg.com/react-native-is-edge-to-edge/-/react-native-is-edge-to-edge-1.2.1.tgz#64e10851abd9d176cbf2b40562f751622bde3358"
integrity sha512-FLbPWl/MyYQWz+KwqOZsSyj2JmLKglHatd3xLZWskXOpRaio4LfEDEz8E/A6uD8QoTHW6Aobw1jbEwK7KMgR7Q==

react-native-keyboard-controller@1.20.7:
version "1.20.7"
resolved "https://registry.yarnpkg.com/react-native-keyboard-controller/-/react-native-keyboard-controller-1.20.7.tgz#e1be1c15a5eb10b96a40a0812d8472e6e4bd8f29"
integrity sha512-G8S5jz1FufPrcL1vPtReATx+jJhT/j+sTqxMIb30b1z7cYEfMlkIzOCyaHgf6IMB2KA9uBmnA5M6ve2A9Ou4kw==
dependencies:
react-native-is-edge-to-edge "^1.2.1"

react-native-lightbox@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/react-native-lightbox/-/react-native-lightbox-0.7.0.tgz#e52b4d7fcc141f59d7b23f0180de535e35b20ec9"
Expand Down Expand Up @@ -6073,10 +6080,10 @@ stream-chat-react-native-core@8.1.0:
version "0.0.0"
uid ""

stream-chat@^9.42.1:
version "9.42.1"
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.42.1.tgz#8b6aa4e3e73a39ed07bb2a4f2a6829ba9354567a"
integrity sha512-o+9wQO4Ruu1A48T0IrX9ZH8+9F5xPgGLPvflaswaPeLyIZXcy8bsQdcT/HSrPmT7gs0WGD3qcbXaAJU5lMQezQ==
stream-chat@^9.44.2:
version "9.44.2"
resolved "https://registry.yarnpkg.com/stream-chat/-/stream-chat-9.44.2.tgz#97d23ae4ac356b352bb0f20a31a29dc63d3ea6f5"
integrity sha512-TXALWeHyWnSn1KlGYEF0sltEHB26vFd26l5m1qlE9Q1XHo9RPPSyLb5mfXqTEY8b2FAv57Ei3hrT8nSXVWacDQ==
dependencies:
"@types/jsonwebtoken" "^9.0.8"
"@types/ws" "^8.5.14"
Expand Down
5 changes: 0 additions & 5 deletions package/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@
"emoji-mart": ">=5.4.0",
"react-native": ">=0.73.0",
"react-native-gesture-handler": ">=2.18.0",
"react-native-keyboard-controller": ">=1.20.2",
"react-native-reanimated": ">=3.16.0",
"react-native-safe-area-context": ">=5.4.1",
"react-native-svg": ">=15.8.0",
Expand All @@ -112,9 +111,6 @@
},
"@emoji-mart/data": {
"optional": true
},
"react-native-keyboard-controller": {
"optional": true
}
},
"devDependencies": {
Expand Down Expand Up @@ -163,7 +159,6 @@
"react-native": "0.80.2",
"react-native-builder-bob": "0.40.11",
"react-native-gesture-handler": "^2.26.0",
"react-native-keyboard-controller": "^1.20.2",
"react-native-reanimated": "3.18.0",
"react-native-safe-area-context": "^5.6.1",
"react-native-svg": "15.12.0",
Expand Down
19 changes: 5 additions & 14 deletions package/src/components/AttachmentPicker/AttachmentPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { useEffect, useMemo, useRef, useState } from 'react';
import {
BackHandler,
EmitterSubscription,
Keyboard,
Platform,
View,
Expand All @@ -21,7 +20,6 @@ import { useComponentsContext } from '../../contexts/componentsContext/Component
import { useTheme } from '../../contexts/themeContext/ThemeContext';
import { useStableCallback } from '../../hooks';
import { BottomSheet } from '../BottomSheetCompatibility/BottomSheet';
import { KeyboardControllerPackage } from '../KeyboardCompatibleView/KeyboardControllerAvoidingView';

dayjs.extend(duration);

Expand All @@ -41,6 +39,7 @@ export const AttachmentPicker = () => {
attachmentPickerBottomSheetHeight,
bottomSheetRef: ref,
bottomInset,
topInset,
disableAttachmentPicker,
} = useAttachmentPickerContext();
const { AttachmentPickerContent, AttachmentPickerSelectionBar } = useComponentsContext();
Expand Down Expand Up @@ -78,18 +77,10 @@ export const AttachmentPicker = () => {
}
closePicker();
};
let keyboardSubscription: EmitterSubscription | null = null;
if (KeyboardControllerPackage?.KeyboardEvents) {
keyboardSubscription = KeyboardControllerPackage.KeyboardEvents.addListener(
'keyboardWillShow',
onKeyboardOpenHandler,
);
} else {
const keyboardShowEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
keyboardSubscription = Keyboard.addListener(keyboardShowEvent, onKeyboardOpenHandler);
}
const keyboardShowEvent = Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
const keyboardSubscription = Keyboard.addListener(keyboardShowEvent, onKeyboardOpenHandler);
return () => {
keyboardSubscription?.remove();
keyboardSubscription.remove();
};
}, [attachmentPickerStore, closePicker]);

Expand All @@ -104,7 +95,7 @@ export const AttachmentPicker = () => {
const initialSnapPoint = attachmentPickerBottomSheetHeight;
const pickerTopInset = Math.max(
0,
windowHeight - attachmentPickerBottomSheetHeight - bottomInset,
windowHeight - topInset - attachmentPickerBottomSheetHeight - bottomInset,
);

/**
Expand Down
31 changes: 23 additions & 8 deletions package/src/components/Channel/Channel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ import {
} from '../../utils/utils';
import { NotificationAnnouncer } from '../Accessibility/NotificationAnnouncer';
import { AttachmentPicker } from '../AttachmentPicker/AttachmentPicker';
import type { KeyboardCompatibleViewProps } from '../KeyboardCompatibleView/KeyboardControllerAvoidingView';
import type { KeyboardCompatibleViewProps } from '../KeyboardCompatibleView/KeyboardCompatibleView';
import { Emoji } from '../MessageMenu/EmojiPickerList';
import { emojis } from '../MessageMenu/emojis';
import { toUnicodeScalarString } from '../MessageMenu/utils/toUnicodeScalarString';
Expand Down Expand Up @@ -496,7 +496,7 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
thread: threadFromProps,
threadList,
threadMessages,
topInset,
topInset = 0,
isOnline,
maximumMessageLimit,
initializeOnMount = true,
Expand Down Expand Up @@ -567,6 +567,18 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
channel,
});

const shouldLoadInitialChannelAtFirstUnreadMessage = useStableCallback((unreadCount?: number) => {
if (messageId || !initialScrollToFirstUnreadMessage || !client.user) {
return false;
}

return (unreadCount ?? channel.countUnread()) > scrollToFirstUnreadThreshold;
});

const hasPendingInitialTargetLoad = useStableCallback(() => {
return !!messageId || shouldLoadInitialChannelAtFirstUnreadMessage();
});

const { setMessages: copyMessagesStateFromChannel, viewabilityChangedCallback } =
usePrunableMessageList({ maximumMessageLimit, setMessages: rawCopyMessagesStateFromChannel });

Expand Down Expand Up @@ -693,6 +705,7 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
const initChannel = async () => {
setLastRead(new Date());
const unreadCount = channel.countUnread();
const shouldLoadAtFirstUnread = shouldLoadInitialChannelAtFirstUnreadMessage(unreadCount);
if (!channel || !shouldSyncChannel) {
return;
}
Expand Down Expand Up @@ -722,13 +735,14 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =

if (messageId) {
await loadChannelAroundMessage({ messageId, setTargetedMessage });
} else if (
initialScrollToFirstUnreadMessage &&
client.user &&
unreadCount > scrollToFirstUnreadThreshold
) {
} else if (shouldLoadAtFirstUnread) {
const clientUserId = client.user?.id;
if (!clientUserId) {
return;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { user, ...ownReadState } = channel.state.read[client.user.id];
const { user, ...ownReadState } = channel.state.read[clientUserId];

await loadChannelAtFirstUnreadMessage({
channelUnreadState: ownReadState,
Expand Down Expand Up @@ -1578,6 +1592,7 @@ const ChannelWithContext = (props: PropsWithChildren<ChannelPropsWithContext>) =
setChannelUnreadState,
setLastRead,
setTargetedMessage,
hasPendingInitialTargetLoad,
targetedMessage,
threadList,
uploadAbortControllerRef,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const useCreateChannelContext = ({
setChannelUnreadState,
setLastRead,
setTargetedMessage,
hasPendingInitialTargetLoad,
targetedMessage,
threadList,
uploadAbortControllerRef,
Expand Down Expand Up @@ -69,6 +70,7 @@ export const useCreateChannelContext = ({
setChannelUnreadState,
setLastRead,
setTargetedMessage,
hasPendingInitialTargetLoad,
targetedMessage,
threadList,
uploadAbortControllerRef,
Expand Down
2 changes: 1 addition & 1 deletion package/src/components/ImageGallery/ImageGallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import { useViewport } from '../../hooks/useViewport';
import { IconProps } from '../../icons/utils/base';
import { ImageGalleryState } from '../../state-store/image-gallery-state-store';
import { FileTypes } from '../../types/types';
import { dismissKeyboard } from '../KeyboardCompatibleView/KeyboardControllerAvoidingView';
import { dismissKeyboard } from '../KeyboardCompatibleView/KeyboardCompatibleView';
import { BottomSheetModal } from '../UIComponents';

export type ImageGalleryActionHandler = () => Promise<void> | void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ import {

import { KeyboardProvider } from '../../contexts/keyboardContext/KeyboardContext';

export type KeyboardCompatibleViewProps = KeyboardAvoidingViewProps;

export const dismissKeyboard = () => {
Keyboard.dismiss();
};

type State = {
bottom: number;
};
Expand Down

This file was deleted.

2 changes: 1 addition & 1 deletion package/src/components/Message/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ import {
MessageStatusTypes,
} from '../../utils/utils';
import type { Thumbnail } from '../Attachment/utils/buildGallery/types';
import { dismissKeyboard } from '../KeyboardCompatibleView/KeyboardControllerAvoidingView';
import { dismissKeyboard } from '../KeyboardCompatibleView/KeyboardCompatibleView';
import { BottomSheetModal } from '../UIComponents';

const createMessageOverlayId = (messageId?: string) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,6 @@ const styles = StyleSheet.create({
containerInner: {
borderTopLeftRadius: components.messageBubbleRadiusGroupBottom,
borderTopRightRadius: components.messageBubbleRadiusGroupBottom,
overflow: 'hidden',
},
contentBody: {
flexShrink: 1,
Expand Down
Loading
Loading