Skip to content

Commit

Permalink
refactor: optimized chat text items
Browse files Browse the repository at this point in the history
  • Loading branch information
Vali-98 committed Aug 16, 2024
1 parent 4c8dd5e commit 005b7aa
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 33 deletions.
13 changes: 6 additions & 7 deletions app/components/ChatMenu/ChatWindow/ChatBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { View, TouchableOpacity, StyleSheet } from 'react-native'
import { useShallow } from 'zustand/react/shallow'

import ChatText from './ChatText'
import ChatTextLast from './ChatTextLast'
import EditorModal from './EditorModal'
import Swipes from './Swipes'

Expand All @@ -27,7 +28,6 @@ const ChatBody: React.FC<ChatTextProps> = ({ id, nowGenerating, messagesLength }
setEditMode(!nowGenerating)
}

const showEllipsis = !message.is_user && isLastMessage && nowGenerating
const hasSwipes = message?.swipes?.length > 1
const showSwipe = !message.is_user && isLastMessage && (hasSwipes || !isGreeting)

Expand All @@ -46,12 +46,11 @@ const ChatBody: React.FC<ChatTextProps> = ({ id, nowGenerating, messagesLength }
style={styles.messageTextContainer}
activeOpacity={0.7}
onLongPress={handleEnableEdit}>
<ChatText
showEllipsis={showEllipsis}
nowGenerating={nowGenerating}
id={id}
isLastMessage={isLastMessage}
/>
{isLastMessage ? (
<ChatTextLast nowGenerating={nowGenerating} id={id} />
) : (
<ChatText nowGenerating={nowGenerating} id={id} />
)}
</TouchableOpacity>

{showSwipe && (
Expand Down
31 changes: 5 additions & 26 deletions app/components/ChatMenu/ChatWindow/ChatText.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
import { Chats, Style, MarkdownStyle } from '@globals'
import { Chats, MarkdownStyle } from '@globals'
import React, { useEffect, useRef } from 'react'
import { StyleSheet, Animated, Easing, LayoutChangeEvent } from 'react-native'
//@ts-expect-error
import Markdown from 'react-native-markdown-package'
//@ts-expect-error
import AnimatedEllipsis from 'rn-animated-ellipsis'
import { useShallow } from 'zustand/react/shallow'

type ChatTextProps = {
showEllipsis: boolean
nowGenerating: boolean
id: number
isLastMessage: boolean
}

const ChatText: React.FC<ChatTextProps> = ({ showEllipsis, nowGenerating, id, isLastMessage }) => {
const ChatText: React.FC<ChatTextProps> = ({ nowGenerating, id }) => {
const animatedHeight = useRef(new Animated.Value(-1)).current
const height = useRef(-1)

Expand All @@ -24,12 +19,6 @@ const ChatText: React.FC<ChatTextProps> = ({ showEllipsis, nowGenerating, id, is
.swipe ?? ''
)

const { buffer } = Chats.useChat(
useShallow((state) => ({
buffer: isLastMessage ? state.buffer : '',
}))
)

const handleAnimateHeight = (newheight: number) => {
animatedHeight.stopAnimation(() =>
Animated.timing(animatedHeight, {
Expand All @@ -52,8 +41,7 @@ const ChatText: React.FC<ChatTextProps> = ({ showEllipsis, nowGenerating, id, is

if (height.current === newHeight) return
height.current = newHeight
const showPadding = nowGenerating && buffer !== ''
handleAnimateHeight(newHeight + (showPadding ? oveflowPadding : 0))
handleAnimateHeight(newHeight)
}
useEffect(() => {
if (!nowGenerating && height.current !== -1) {
Expand All @@ -68,24 +56,15 @@ const ChatText: React.FC<ChatTextProps> = ({ showEllipsis, nowGenerating, id, is
return (
<Animated.View
style={{
height: __DEV__ ? 'auto' : animatedHeight, // this is a dev due to height animations being
height: __DEV__ ? 'auto' : animatedHeight, // dev fix for slow emulator animations
overflow: 'scroll',
}}>
{showEllipsis && buffer === '' && (
<AnimatedEllipsis
style={{
color: Style.getColor('primary-text2'),
fontSize: 20,
}}
/>
)}

<Markdown
onLayout={handleContentSizeChange}
style={styles.messageText}
rules={{ rules: MarkdownStyle.Rules }}
styles={MarkdownStyle.Format}>
{nowGenerating && isLastMessage ? buffer.trim() : mes.trim()}
{mes.trim()}
</Markdown>
</Animated.View>
)
Expand Down
100 changes: 100 additions & 0 deletions app/components/ChatMenu/ChatWindow/ChatTextLast.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { Chats, Style, MarkdownStyle } from '@globals'
import React, { useEffect, useRef } from 'react'
import { StyleSheet, Animated, Easing, LayoutChangeEvent } from 'react-native'
//@ts-expect-error
import Markdown from 'react-native-markdown-package'
//@ts-expect-error
import AnimatedEllipsis from 'rn-animated-ellipsis'
import { useShallow } from 'zustand/react/shallow'

type ChatTextProps = {
nowGenerating: boolean
id: number
}

const ChatTextLast: React.FC<ChatTextProps> = ({ nowGenerating, id }) => {
const animatedHeight = useRef(new Animated.Value(-1)).current
const height = useRef(-1)

const mes = Chats.useChat(
(state) =>
state?.data?.messages?.[id]?.swipes?.[state?.data?.messages?.[id].swipe_id ?? -1]
.swipe ?? ''
)

const { buffer } = Chats.useChat(
useShallow((state) => ({
buffer: state.buffer,
}))
)

const handleAnimateHeight = (newheight: number) => {
animatedHeight.stopAnimation(() =>
Animated.timing(animatedHeight, {
toValue: newheight,
duration: 200,
useNativeDriver: false,
easing: Easing.inOut((x) => x * x),
}).start()
)
}
const handleContentSizeChange = (event: LayoutChangeEvent) => {
const newHeight = event.nativeEvent.layout.height
const oveflowPadding = 12

if (height.current === -1) {
height.current = newHeight
animatedHeight.setValue(newHeight)
return
}

if (height.current === newHeight) return
height.current = newHeight
const showPadding = nowGenerating && buffer !== ''
handleAnimateHeight(newHeight + (showPadding ? oveflowPadding : 0))
}

useEffect(() => {
if (!nowGenerating && height.current !== -1) {
handleAnimateHeight(height.current)
} else if (nowGenerating && !mes) {
// NOTE: this assumes that mes is empty due to a swipe and may break, but unlikely
height.current = 0
handleAnimateHeight(height.current)
}
}, [nowGenerating])

return (
<Animated.View
style={{
height: __DEV__ ? 'auto' : animatedHeight, // dev fix for slow emulator animations
overflow: 'scroll',
}}>
{nowGenerating && buffer === '' && (
<AnimatedEllipsis
style={{
color: Style.getColor('primary-text2'),
fontSize: 20,
}}
/>
)}

<Markdown
onLayout={handleContentSizeChange}
style={styles.messageText}
rules={{ rules: MarkdownStyle.Rules }}
styles={MarkdownStyle.Format}>
{nowGenerating ? buffer.trim() : mes.trim()}
</Markdown>
</Animated.View>
)
}

export default ChatTextLast

const styles = StyleSheet.create({
messageText: {
borderWidth: 2,
borderColor: 'red',
},
})

0 comments on commit 005b7aa

Please sign in to comment.