feat(ui, wip): 对话页面

This commit is contained in:
CrescentLeaf
2026-01-01 01:06:21 +08:00
parent cf560909e7
commit 3514f87699
4 changed files with 47 additions and 9 deletions

View File

@@ -12,6 +12,7 @@ import TextFieldPreference from "../preference/TextFieldPreference"
import * as React from 'react' import * as React from 'react'
import ChatMessageContainer from "./ChatMessageContainer" import ChatMessageContainer from "./ChatMessageContainer"
import AppStateContext from "../app-state/AppStateContext" import AppStateContext from "../app-state/AppStateContext"
import ChatPanel, { ChatPanelRef } from "./ChatPanel"
interface MduiTabFitSizeArgs extends React.HTMLAttributes<HTMLElement & Tab> { interface MduiTabFitSizeArgs extends React.HTMLAttributes<HTMLElement & Tab> {
value: string value: string
@@ -41,6 +42,9 @@ export default function ChatFragment({
const chatPanelRef = React.useRef<HTMLElement>() const chatPanelRef = React.useRef<HTMLElement>()
const inputRef = React.useRef<TextField>() const inputRef = React.useRef<TextField>()
const chatPagePanelRef = React.useRef<ChatPanelRef>()
return ( return (
<div style={{ <div style={{
@@ -126,6 +130,7 @@ export default function ChatFragment({
const scrollTop = (e.target as HTMLDivElement).scrollTop const scrollTop = (e.target as HTMLDivElement).scrollTop
if (scrollTop == 0) { if (scrollTop == 0) {
// 加载更多 // 加载更多
chatPagePanelRef.current?.setOffset(chatPagePanelRef.current.getOffset() + 15)
} }
}}> }}>
<div style={{ <div style={{
@@ -135,7 +140,7 @@ export default function ChatFragment({
}}> }}>
{/* 这里显示一些提示 */} {/* 这里显示一些提示 */}
</div> </div>
<ChatMessageContainer chatInfo={chatInfo} /> <ChatPanel ref={chatPagePanelRef} chat={chatInfo} />
{ {
// 输入框 // 输入框
} }
@@ -180,8 +185,10 @@ export default function ChatFragment({
}}></mdui-button-icon> }}></mdui-button-icon>
<mdui-button-icon icon="send" style={{ <mdui-button-icon icon="send" style={{
marginRight: '7px', marginRight: '7px',
}} onClick={() => { }} onClick={async () => {
// 发送消息 // 发送消息
await chatInfo.sendMessageOrThrow(inputRef.current!.value)
inputRef.current!.value = ''
}}></mdui-button-icon> }}></mdui-button-icon>
<div style={{ <div style={{
display: 'none' display: 'none'

View File

@@ -0,0 +1,5 @@
import { Message } from "lingchair-client-protocol"
export default function ChatMessage({ message }: { message: Message }) {
return null
}

View File

@@ -1,13 +1,7 @@
import { Chat, Message } from 'lingchair-client-protocol' import { Chat, Message } from 'lingchair-client-protocol'
import * as React from 'react' import * as React from 'react'
export default function ChatMessageContainer({ export default function ChatMessageContainer({ messages }: { messages: Message[] }) {
chat,
}: {
chat: Chat
}) {
const [messages, setMessages] = React.useState<Message[]>()
return ( return (
<div style={{ <div style={{
display: 'flex', display: 'flex',

View File

@@ -0,0 +1,32 @@
import { Chat, Message } from "lingchair-client-protocol"
import ChatMessageContainer from "./ChatMessageContainer"
import useAsyncEffect from "../../utils/useAsyncEffect"
import * as React from 'react'
function ChatPanelInner({ chat }: { chat: Chat }, ref: React.ForwardedRef<any>) {
const [messages, setMessages] = React.useState<Message[]>([])
const [offset, setOffset] = React.useState(0)
React.useImperativeHandle(ref, () => {
return {
setOffset: (offset: number) => setOffset(offset),
getOffset: () => offset,
}
}, [chat])
useAsyncEffect(async () => {
const messages = await chat.getMessagesOrThrow({ offset })
setMessages(messages)
}, [chat, offset])
return <ChatMessageContainer messages={messages} />
}
const ChatPanel = React.forwardRef(ChatPanelInner)
export type ChatPanelRef = {
setOffset: (offset: number) => void
getOffset: () => number
}
export default ChatPanel