11import { createComponent , Shade } from '@furystack/shades'
2+ import { Paper } from '@furystack/shades-common-components'
23import { marked } from 'marked'
34import { ErrorDisplay } from '../../components/error-display.js'
5+ import { WebsocketNotificationsService } from '../../services/websocket-events.js'
46import { AiChatMessageService } from './ai-chat-message-service.js'
57
68export const AiChatMessageList = Shade < {
@@ -14,7 +16,7 @@ export const AiChatMessageList = Shade<{
1416 height : 'calc(100% - 32px)' ,
1517 overflowY : 'auto' ,
1618 } ,
17- render : ( { useObservable, injector, props } ) => {
19+ render : ( { useObservable, injector, props, element , useDisposable } ) => {
1820 const { selectedChatId } = props
1921 const aiChatService = injector . getInstance ( AiChatMessageService )
2022
@@ -27,6 +29,31 @@ export const AiChatMessageList = Shade<{
2729 } ) ,
2830 )
2931
32+ const wsService = injector . getInstance ( WebsocketNotificationsService )
33+
34+ useDisposable ( 'webSocketSubscription' , ( ) =>
35+ wsService . subscribe ( 'onMessage' , async ( message ) => {
36+ if ( message . type !== 'ai-chat-message-added' ) {
37+ return
38+ }
39+ if ( message . aiChatMessage . aiChatId !== selectedChatId ) {
40+ return
41+ }
42+ scrollToBottom ( 'smooth' )
43+ } ) ,
44+ )
45+
46+ const scrollToBottom = ( behavior : ScrollBehavior = 'instant' ) => {
47+ setTimeout ( ( ) => {
48+ requestAnimationFrame ( ( ) => {
49+ element . scrollTo ( {
50+ top : element . scrollHeight ,
51+ behavior,
52+ } )
53+ } )
54+ } , 1 )
55+ }
56+
3057 if ( ! messages ?. value ) {
3158 return < div > Loading messages...</ div >
3259 }
@@ -43,21 +70,18 @@ export const AiChatMessageList = Shade<{
4370 } )
4471 }
4572
73+ scrollToBottom ( )
74+
4675 return (
4776 < >
4877 { messages . value . result . entries . map ( ( message ) => {
4978 const innerHTML = marked . parse ( message . content )
5079
5180 return (
52- < div
53- style = { {
54- padding : '8px' ,
55- borderBottom : '1px solid #ccc' ,
56- } }
57- >
81+ < Paper elevation = { 1 } style = { { padding : '8px' , margin : '4px 0' , filter : 'brightness(0.9)' } } >
5882 < strong > { message . role } </ strong >
5983 < div style = { { marginTop : '4px' } } innerHTML = { innerHTML as string } />
60- </ div >
84+ </ Paper >
6185 )
6286 } ) }
6387 </ >
0 commit comments