Skip to content
Draft
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ interface QuickReplies {
- **`messages`** _(Array)_ - Messages to display
- **`isTyping`** _(Bool)_ - Typing Indicator state; default `false`. If you use`renderFooter` it will override this.
- **`isKeyboardInternallyHandled`** _(Bool)_ - Determine whether to handle keyboard awareness inside the plugin. If you have your own keyboard handling outside the plugin set this to false; default is `true`
- **`disableKeyboardController`** _(Bool)_ - Completely disable react-native-keyboard-controller. Useful when using react-native-navigation or other conflicting keyboard libraries; default is `false`
- **`text`** _(String)_ - Input text; default is `undefined`, but if specified, it will override GiftedChat's internal state (e.g. for redux; [see notes below](#notes-for-redux))
- **`placeholder`** _(String)_ - Placeholder when `text` is empty; default is `'Type a message...'`
- **`messageIdGenerator`** _(Function)_ - Generate an id for new messages. Defaults to UUID v4, generated by [uuid](https://github.com/kelektiv/node-uuid)
Expand Down
26 changes: 23 additions & 3 deletions src/GiftedChat/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
minComposerHeight = MIN_COMPOSER_HEIGHT,
maxComposerHeight = MAX_COMPOSER_HEIGHT,
isKeyboardInternallyHandled = true,
disableKeyboardController = false,
} = props

const actionSheetRef = useRef<ActionSheetProviderRef>(null)
Expand All @@ -112,7 +113,16 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
const [text, setText] = useState<string | undefined>(() => props.text || '')
const [isTypingDisabled, setIsTypingDisabled] = useState<boolean>(false)

const keyboard = useReanimatedKeyboardAnimation()
// Always call the hook, but conditionally use its data
const keyboardControllerData = useReanimatedKeyboardAnimation()

// Create a mock keyboard object when disabled
const keyboard = useMemo(() => {
if (disableKeyboardController)
return { height: { value: 0 } }
return keyboardControllerData
}, [disableKeyboardController, keyboardControllerData])

const trackingKeyboardMovement = useSharedValue(false)
const debounceEnableTypingTimeoutId = useRef<ReturnType<typeof setTimeout>>(undefined)
const keyboardOffsetBottom = useSharedValue(0)
Expand Down Expand Up @@ -380,9 +390,14 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
setText(props.text)
}, [props.text])

// Only set up keyboard animation when keyboard controller is enabled
useAnimatedReaction(
() => -keyboard.height.value,
() => disableKeyboardController ? 0 : -keyboard.height.value,
(value, prevValue) => {
// Skip keyboard handling when disabled
if (disableKeyboardController)
return

if (prevValue !== null && value !== prevValue) {
const isKeyboardMovingUp = value > prevValue
if (isKeyboardMovingUp !== trackingKeyboardMovement.value) {
Expand Down Expand Up @@ -420,6 +435,7 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
disableTyping,
debounceEnableTyping,
bottomOffset,
disableKeyboardController,
]
)

Expand All @@ -433,7 +449,7 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
>
{isInitialized
? (
<Animated.View style={[stylesCommon.fill, isKeyboardInternallyHandled && contentStyleAnim]}>
<Animated.View style={[stylesCommon.fill, (isKeyboardInternallyHandled && !disableKeyboardController) && contentStyleAnim]}>
{renderMessages}
{inputToolbarFragment}
</Animated.View>
Expand All @@ -448,6 +464,10 @@ function GiftedChat<TMessage extends IMessage = IMessage> (
}

function GiftedChatWrapper<TMessage extends IMessage = IMessage> (props: GiftedChatProps<TMessage>) {
// Don't use KeyboardProvider when keyboard controller is disabled
if (props.disableKeyboardController)
return <GiftedChat<TMessage> {...props} />

return (
<KeyboardProvider>
<GiftedChat<TMessage> {...props} />
Expand Down
2 changes: 2 additions & 0 deletions src/GiftedChat/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ export interface GiftedChatProps<TMessage extends IMessage> extends Partial<Mess
isLoadingEarlier?: boolean
/* Determine whether to handle keyboard awareness inside the plugin. If you have your own keyboard handling outside the plugin set this to false; default is `true` */
isKeyboardInternallyHandled?: boolean
/* Completely disable react-native-keyboard-controller. Useful when using react-native-navigation or other conflicting keyboard libraries; default is `false` */
disableKeyboardController?: boolean
/* Whether to render an avatar for the current user; default is false, only show avatars for other users */
showUserAvatar?: boolean
/* When false, avatars will only be displayed when a consecutive message is from the same user on the same day; default is false */
Expand Down
25 changes: 25 additions & 0 deletions src/__tests__/GiftedChat.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,28 @@ it('should render <GiftedChat/> and compare with snapshot', () => {

expect(tree.toJSON()).toMatchSnapshot()
})

it('should render <GiftedChat/> with disableKeyboardController=true', () => {
let tree

renderer.act(() => {
(useReanimatedKeyboardAnimation as jest.Mock).mockReturnValue({
height: {
value: 0,
},
})

tree = renderer.create(
<GiftedChat
messages={messages}
onSend={() => {}}
user={{
_id: 1,
}}
disableKeyboardController={true}
/>
)
})

expect(tree.toJSON()).toMatchSnapshot()
})
25 changes: 25 additions & 0 deletions src/__tests__/__snapshots__/GiftedChat.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,28 @@ exports[`should render <GiftedChat/> and compare with snapshot 1`] = `
</View>
</KeyboardProvider>
`;

exports[`should render <GiftedChat/> with disableKeyboardController=true 1`] = `
<View
style={
{
"flex": 1,
}
}
>
<View
onLayout={[Function]}
style={
[
{
"flex": 1,
},
{
"overflow": "hidden",
},
]
}
testID="GC_WRAPPER"
/>
</View>
`;