Skip to content

Instantly share code, notes, and snippets.

@Karthik-B-06
Last active January 14, 2024 08:09
Show Gist options
  • Save Karthik-B-06/512831203198bf5116c9395b4928e501 to your computer and use it in GitHub Desktop.
Save Karthik-B-06/512831203198bf5116c9395b4928e501 to your computer and use it in GitHub Desktop.
import React, { useCallback } from "react";
import {
NativeSyntheticEvent,
Platform,
Pressable,
TextInputContentSizeChangeEventData,
TextInputProps,
} from "react-native";
import Animated, {
Layout,
useAnimatedProps,
useAnimatedStyle,
useSharedValue,
} from "react-native-reanimated";
import Svg, { Path, Rect } from "react-native-svg";
import { BottomSheetTextInput } from "@gorhom/bottom-sheet";
import { TEXT_INPUT_CONTAINER_HEIGHT } from "../../../constants";
import { useChatWindowContext } from "../../../context";
import { useSendMessage } from "../../../store";
import { tailwind } from "../../../theme";
import { Icon } from "../../common";
const AnimatedTextInput =
Animated.createAnimatedComponent(BottomSheetTextInput);
const INIT_TEXTINPUT_HEIGHT = 36;
// Based on Line height of text
const MIN_TEXTINPUT_HEIGHT = 20;
// Value based on initial height + 3 new line texts
const MAX_TEXTINPUT_HEIGHT = 76;
type MessageTextInputProps = {};
export const MessageTextInput = ({}: MessageTextInputProps) => {
const textInputHeight = useSharedValue(INIT_TEXTINPUT_HEIGHT);
const messageText = useSharedValue("");
const { textInputRef, setIsTextInputFocused } = useChatWindowContext();
const setMessageText = useSendMessage(state => state.setMessageText);
const onContentSizeChange = (
event: NativeSyntheticEvent<TextInputContentSizeChangeEventData>,
) => {
"worklet";
const contentHeight = event.nativeEvent.contentSize.height;
if (Platform.OS === "ios") {
const multiplier = contentHeight / MIN_TEXTINPUT_HEIGHT - 1;
textInputHeight.value = Math.min(
MIN_TEXTINPUT_HEIGHT * multiplier + INIT_TEXTINPUT_HEIGHT,
MAX_TEXTINPUT_HEIGHT,
);
}
if (Platform.OS === "android") {
const multiplier = contentHeight / TEXT_INPUT_CONTAINER_HEIGHT - 1;
textInputHeight.value = Math.min(
MIN_TEXTINPUT_HEIGHT * multiplier + INIT_TEXTINPUT_HEIGHT,
MAX_TEXTINPUT_HEIGHT,
);
}
};
const animatedProps = useAnimatedProps(() => {
return {
text: messageText.value,
} as unknown as TextInputProps;
});
const onChangeText = (text: string) => {
messageText.value = text.trimEnd();
setMessageText(text);
if (text.length === 0) {
textInputHeight.value = INIT_TEXTINPUT_HEIGHT;
}
};
const handleFocus = useCallback(() => {
setIsTextInputFocused(true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const handleBlur = useCallback(() => {
setIsTextInputFocused(false);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const animatedTextInputHeight = useAnimatedStyle(() => {
return {
height: textInputHeight.value,
};
}, []);
return (
<AnimatedTextInput
// @ts-ignore
ref={textInputRef}
layout={Layout.springify().damping(20).stiffness(180)}
onChangeText={onChangeText}
numberOfLines={3}
multiline
enablesReturnKeyAutomatically
style={[
tailwind.style(
"flex-1 text-base font-inter-normal-24 tracking-[0.24px] min-h-9 leading-[20px] py-2 pl-3 pr-[36px] rounded-2xl text-gray-950",
isPrivateMessage ? "bg-amber-100" : "bg-blackA-A4",
),
]}
placeholderTextColor={tailwind.color("bg-gray-800")}
placeholder="Message..."
onContentSizeChange={onContentSizeChange}
onSubmitEditing={() => (messageText.value = "")}
returnKeyType={"default"}
textAlignVertical="top"
underlineColorAndroid="transparent"
onFocus={handleFocus}
onBlur={handleBlur}
animatedProps={animatedProps}
/>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment