聊天详情进入后滚动到最新消息
This commit is contained in:
@@ -104,6 +104,8 @@ const FALLBACK_RUNTIME_INFO: VoiceRuntimeInfo = {
|
|||||||
supportsMp3Record: true,
|
supportsMp3Record: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CHAT_BOTTOM_ANCHOR_ID = 'chat-bottom'
|
||||||
|
|
||||||
function compareVersion(left: string, right: string): number {
|
function compareVersion(left: string, right: string): number {
|
||||||
const leftParts = left.split('.').map((item) => Number(item) || 0)
|
const leftParts = left.split('.').map((item) => Number(item) || 0)
|
||||||
const rightParts = right.split('.').map((item) => Number(item) || 0)
|
const rightParts = right.split('.').map((item) => Number(item) || 0)
|
||||||
@@ -224,6 +226,7 @@ export default function ChatDetail() {
|
|||||||
const [recording, setRecording] = useState(false)
|
const [recording, setRecording] = useState(false)
|
||||||
const [playingMessageId, setPlayingMessageId] = useState<number | null>(null)
|
const [playingMessageId, setPlayingMessageId] = useState<number | null>(null)
|
||||||
const [recordHint, setRecordHint] = useState('长按开始留言')
|
const [recordHint, setRecordHint] = useState('长按开始留言')
|
||||||
|
const [scrollTarget, setScrollTarget] = useState('')
|
||||||
const audioContextRef = useRef<Taro.InnerAudioContext | null>(null)
|
const audioContextRef = useRef<Taro.InnerAudioContext | null>(null)
|
||||||
const recorderManagerRef = useRef<Taro.RecorderManager | null>(null)
|
const recorderManagerRef = useRef<Taro.RecorderManager | null>(null)
|
||||||
const activeConversationIdRef = useRef(initialConversationId)
|
const activeConversationIdRef = useRef(initialConversationId)
|
||||||
@@ -233,6 +236,18 @@ export default function ChatDetail() {
|
|||||||
const runtimeInfoRef = useRef<VoiceRuntimeInfo>(FALLBACK_RUNTIME_INFO)
|
const runtimeInfoRef = useRef<VoiceRuntimeInfo>(FALLBACK_RUNTIME_INFO)
|
||||||
const recordStartedAtRef = useRef<number>(0)
|
const recordStartedAtRef = useRef<number>(0)
|
||||||
const playingMessageIdRef = useRef<number | null>(null)
|
const playingMessageIdRef = useRef<number | null>(null)
|
||||||
|
const scrollTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null)
|
||||||
|
|
||||||
|
const scrollToBottom = () => {
|
||||||
|
if (scrollTimerRef.current) {
|
||||||
|
clearTimeout(scrollTimerRef.current)
|
||||||
|
}
|
||||||
|
setScrollTarget('')
|
||||||
|
scrollTimerRef.current = setTimeout(() => {
|
||||||
|
setScrollTarget(CHAT_BOTTOM_ANCHOR_ID)
|
||||||
|
scrollTimerRef.current = null
|
||||||
|
}, 80)
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
runtimeInfoRef.current = readVoiceRuntimeInfo()
|
runtimeInfoRef.current = readVoiceRuntimeInfo()
|
||||||
@@ -290,6 +305,15 @@ export default function ChatDetail() {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
if (scrollTimerRef.current) {
|
||||||
|
clearTimeout(scrollTimerRef.current)
|
||||||
|
scrollTimerRef.current = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
activeConversationIdRef.current = activeConversationId
|
activeConversationIdRef.current = activeConversationId
|
||||||
}, [activeConversationId])
|
}, [activeConversationId])
|
||||||
@@ -325,6 +349,9 @@ export default function ChatDetail() {
|
|||||||
}
|
}
|
||||||
const msgs = await getMessages(conversationId, conversationSource, decodedConversationTypeName)
|
const msgs = await getMessages(conversationId, conversationSource, decodedConversationTypeName)
|
||||||
setMessages(msgs)
|
setMessages(msgs)
|
||||||
|
if (msgs.length > 0) {
|
||||||
|
scrollToBottom()
|
||||||
|
}
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('[chat-detail] load failed:', error)
|
console.error('[chat-detail] load failed:', error)
|
||||||
Taro.showToast({
|
Taro.showToast({
|
||||||
@@ -621,7 +648,7 @@ export default function ChatDetail() {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
<ScrollView className='chat-list' scrollY scrollWithAnimation>
|
<ScrollView className='chat-list' scrollY scrollWithAnimation scrollIntoView={scrollTarget}>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<View className='empty-chat'>
|
<View className='empty-chat'>
|
||||||
<Text className='empty-chat-text'>加载中...</Text>
|
<Text className='empty-chat-text'>加载中...</Text>
|
||||||
@@ -669,6 +696,7 @@ export default function ChatDetail() {
|
|||||||
</View>
|
</View>
|
||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
|
<View id={CHAT_BOTTOM_ANCHOR_ID} />
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
{character.canSend && character.childId && (
|
{character.canSend && character.childId && (
|
||||||
|
|||||||
Reference in New Issue
Block a user