@@ -8,6 +8,20 @@ import { QueryBuilder } from "~/lib/query_builder";
88import { MainContext , ShellContext , use_context } from "../context" ;
99import Image from "../widgets/image" ;
1010
11+ const messageStatusText = ( message : Message | undefined ) => {
12+ if ( message ?. status === "sending" ) return "发送中" ;
13+ if ( message ?. status === "failed" ) return message . error_message ?? "发送失败" ;
14+ return "已发送" ;
15+ } ;
16+
17+ const messageTimeText = ( message : Message | undefined ) => {
18+ if ( ! message ) return "" ;
19+ return new Date ( message . created_at ) . toLocaleTimeString ( [ ] , {
20+ hour : "2-digit" ,
21+ minute : "2-digit" ,
22+ } ) ;
23+ } ;
24+
1125export default function ChatBar ( props : { chat_user : User } ) {
1226 const shell_store = use_context ( ShellContext ) ;
1327 const main_store = use_context ( MainContext ) ;
@@ -17,9 +31,21 @@ export default function ChatBar(props: { chat_user: User }) {
1731 if ( ! u ) throw new Error ( "用户不存在" ) ;
1832 return await main_store . sqlite . query < Message > (
1933 QueryBuilder . selectFrom ( "chat_message" )
20- . select ( [ "chat_user_id" , "timestamp" , "content" ] )
34+ . select ( [
35+ "id" ,
36+ "owner_id" ,
37+ "chat_user_id" ,
38+ "sender_id" ,
39+ "content" ,
40+ "status" ,
41+ "created_at" ,
42+ "sort_at" ,
43+ "retry_count" ,
44+ "error_message" ,
45+ ] )
2146 . where ( "owner_id" , "=" , u . id )
2247 . where ( "chat_user_id" , "=" , props . chat_user . id )
48+ . orderBy ( "sort_at" , "asc" )
2349 . compile ( ) ,
2450 ) ;
2551 } ) ;
@@ -70,56 +96,61 @@ export default function ChatBar(props: { chat_user: User }) {
7096 } }
7197 >
7298 < For each = { message_list_virtualizer . getVirtualItems ( ) } >
73- { ( v ) => (
74- < div
75- class = { twMerge (
76- "chat p-0" ,
77- messages ( ) ?. at ( v . index ) ?. sender_id === props . chat_user . id
78- ? "chat-start"
79- : "chat-end" ,
80- ) }
81- >
82- < div class = "chat-image avatar" >
83- < Show
84- keyed
85- when = {
86- messages ( ) ?. at ( v . index ) ?. sender_id ===
87- props . chat_user . id
88- ? props . chat_user . avatar
89- : user ( ) ?. avatar
90- }
91- fallback = {
92- < UserIcon class = "size-10 rounded-full bg-base-300" />
93- }
94- >
95- { ( avatar ) => (
96- < Image class = "size-10 rounded-full" image = { avatar } />
97- ) }
98- </ Show >
99- </ div >
100- < div class = "chat-header items-center" >
101- < span
102- class = { twMerge (
103- "text-sm text-base-content font-bold" ,
104- messages ( ) ?. at ( v . index ) ?. sender_id ===
105- props . chat_user . id
106- ? undefined
107- : "order-1" ,
108- ) }
109- >
110- { messages ( ) ?. at ( v . index ) ?. sender_id ===
111- props . chat_user . id
112- ? props . chat_user . name
113- : user ( ) ?. name }
99+ { ( v ) => {
100+ const message = ( ) => messages ( ) ?. at ( v . index ) ;
101+ const is_remote_message = ( ) =>
102+ message ( ) ?. sender_id === props . chat_user . id ;
103+ return (
104+ < div
105+ class = { twMerge (
106+ "chat p-0" ,
107+ is_remote_message ( ) ? "chat-start" : "chat-end" ,
108+ ) }
109+ >
110+ < div class = "chat-image avatar" >
111+ < Show
112+ keyed
113+ when = {
114+ is_remote_message ( )
115+ ? props . chat_user . avatar
116+ : user ( ) ?. avatar
117+ }
118+ fallback = {
119+ < UserIcon class = "size-10 rounded-full bg-base-300" />
120+ }
121+ >
122+ { ( avatar ) => (
123+ < Image
124+ class = "size-10 rounded-full"
125+ image = { avatar }
126+ />
127+ ) }
128+ </ Show >
129+ </ div >
130+ < div class = "chat-header items-center" >
131+ < span
132+ class = { twMerge (
133+ "text-sm text-base-content font-bold" ,
134+ is_remote_message ( ) ? undefined : "order-1" ,
135+ ) }
136+ >
137+ { is_remote_message ( )
138+ ? props . chat_user . name
139+ : user ( ) ?. name }
140+ </ span >
141+ < time class = "text-base-content/60" >
142+ { messageTimeText ( message ( ) ) }
143+ </ time >
144+ </ div >
145+ < span class = "border rounded-box bg-base-100 border-neutral-200 p-2" >
146+ { message ( ) ?. content }
114147 </ span >
115- < time class = "text-base-content/60" > 12:45</ time >
148+ < div class = "chat-footer text-base-content/60" >
149+ { messageStatusText ( message ( ) ) }
150+ </ div >
116151 </ div >
117- < span class = "border rounded-box bg-base-100 border-neutral-200 p-2" >
118- { messages ( ) ?. at ( v . index ) ?. content }
119- </ span >
120- < div class = "chat-footer text-base-content/60" > 已读</ div >
121- </ div >
122- ) }
152+ ) ;
153+ } }
123154 </ For >
124155 </ div >
125156 </ div >
0 commit comments