diff --git a/.prettierrc.json b/.prettierrc.json index 1c533245..1f3237ec 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,5 +1,5 @@ { "tabWidth": 4, "printWidth": 120, - "singleQuote": true + "singleQuote": false } diff --git a/example/app/(tabs)/index.tsx b/example/app/(tabs)/index.tsx index 9a97f75d..f9025150 100644 --- a/example/app/(tabs)/index.tsx +++ b/example/app/(tabs)/index.tsx @@ -80,6 +80,10 @@ const data: ListElement[] = [ title: "Chat keyboard", url: "/chat-keyboard", }, + { + title: "Chat keyboard overlap", + url: "/chat-keyboard-overlap", + }, { title: "Movies FlashList", url: "/movies-flashlist", diff --git a/example/app/chat-keyboard-overlap/index.tsx b/example/app/chat-keyboard-overlap/index.tsx new file mode 100644 index 00000000..5813743e --- /dev/null +++ b/example/app/chat-keyboard-overlap/index.tsx @@ -0,0 +1,252 @@ +import { type PropsWithChildren, useState } from "react"; +import { BlurView } from "expo-blur"; +import { Button, Platform, StyleSheet, Text, TextInput, View } from "react-native"; +import { KeyboardGestureArea, KeyboardProvider, KeyboardStickyView } from "react-native-keyboard-controller"; +import { SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context"; + +import { KeyboardAvoidingLegendList } from "@legendapp/list/keyboard"; + +type Message = { + id: string; + text: string; + sender: "user" | "bot"; + timeStamp: number; +}; + +let idCounter = 0; +const MS_PER_SECOND = 1000; + +const defaultChatMessages: Message[] = [ + { + id: String(idCounter++), + sender: "user", + text: "Hi, I have a question about your product", + timeStamp: Date.now() - MS_PER_SECOND * 5, + }, + { + id: String(idCounter++), + sender: "bot", + text: "Hello there! How can I assist you today?", + timeStamp: Date.now() - MS_PER_SECOND * 4, + }, + { + id: String(idCounter++), + sender: "user", + text: "I'm looking for information about pricing plans", + timeStamp: Date.now() - MS_PER_SECOND * 4, + }, + { + id: String(idCounter++), + sender: "bot", + text: "We offer several pricing tiers based on your needs", + timeStamp: Date.now() - MS_PER_SECOND * 4, + }, + { + id: String(idCounter++), + sender: "bot", + text: "Our basic plan starts at $9.99 per month", + timeStamp: Date.now() - MS_PER_SECOND * 4, + }, + { + id: String(idCounter++), + sender: "user", + text: "Do you offer any discounts for annual billing?", + timeStamp: Date.now() - MS_PER_SECOND * 4, + }, + { + id: String(idCounter++), + sender: "bot", + text: "Yes! You can save 20% with our annual billing option", + timeStamp: Date.now() - MS_PER_SECOND * 4, + }, + { + id: String(idCounter++), + sender: "user", + text: "That sounds great. What features are included?", + timeStamp: Date.now() - MS_PER_SECOND * 4, + }, + { + id: String(idCounter++), + sender: "bot", + text: "The basic plan includes all core features plus 10GB storage", + timeStamp: Date.now() - MS_PER_SECOND * 4, + }, + { + id: String(idCounter++), + sender: "bot", + text: "Premium plans include priority support and additional tools", + timeStamp: Date.now() - MS_PER_SECOND * 4, + }, + { + id: String(idCounter++), + sender: "user", + text: "I think the basic plan would work for my needs", + timeStamp: Date.now() - MS_PER_SECOND * 4, + }, + { + id: String(idCounter++), + sender: "bot", + text: "Perfect! I can help you get set up with that", + timeStamp: Date.now() - MS_PER_SECOND * 4, + }, + { + id: String(idCounter++), + sender: "user", + text: "Thanks for your help so far", + timeStamp: Date.now() - MS_PER_SECOND * 4, + }, + { + id: String(idCounter++), + sender: "bot", + text: "You're welcome! Is there anything else I can assist with today?", + timeStamp: Date.now() - MS_PER_SECOND * 3, + }, +]; + +function ChatMessage({ item }: { item: Message }) { + return ( + <> + + {item.text} + + + {new Date(item.timeStamp).toLocaleTimeString()} + + + ); +} + +const ChatKeyboard = () => { + const [messages, setMessages] = useState(defaultChatMessages); + const [inputText, setInputText] = useState(""); + const insets = useSafeAreaInsets(); + + const sendMessage = () => { + const text = inputText || "Empty message"; + if (text.trim()) { + setMessages((messagesNew) => [ + ...messagesNew, + { id: String(idCounter++), sender: "user", text: text, timeStamp: Date.now() }, + ]); + setInputText(""); + setTimeout(() => { + setMessages((messagesNew) => [ + ...messagesNew, + { + id: String(idCounter++), + sender: "bot", + text: `Answer: ${text.toUpperCase()}`, + timeStamp: Date.now(), + }, + ]); + }, 300); + } + }; + + return ( + + + item.id} + maintainScrollAtEnd + maintainVisibleContentPosition + renderItem={ChatMessage} + safeAreaInsetBottom={insets.bottom} + style={styles.list} + /> + + + + +