1+ <!DOCTYPE html>
2+ < html lang ="en " xmlns:th ="http://www.thymeleaf.org ">
3+ < head >
4+ < meta charset ="UTF-8 "/>
5+ < title > Chat</ title >
6+ < script src ="https://code.jquery.com/jquery-3.2.1.min.js "
7+ integrity ="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4= "
8+ crossorigin ="anonymous "> </ script >
9+ <!-- Latest compiled and minified CSS -->
10+ < link rel ="stylesheet " href ="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css "
11+ integrity ="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u " crossorigin ="anonymous "/>
12+
13+ <!-- Optional theme -->
14+ < link rel ="stylesheet " href ="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css "
15+ integrity ="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp " crossorigin ="anonymous "/>
16+
17+ <!-- Awesome Font-->
18+ < link rel ="stylesheet " href ="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css ">
19+
20+ <!-- Latest compiled and minified JavaScript -->
21+ < script src ="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js "
22+ integrity ="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa "
23+ crossorigin ="anonymous "> </ script >
24+ < script src ='https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js '> </ script >
25+ < script src ='https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment-with-locales.min.js '> </ script >
26+
27+ < script src ='/rsocket-types.js '> </ script >
28+ < script src ='/rsocket-flowable.js '> </ script >
29+ < script src ='/rsocket-core.js '> </ script >
30+ < script src ='/rsocket-websocket-client.js '> </ script >
31+
32+ < style >
33+ .chats-row div {
34+ height : 50% ;
35+ border : 1px solid # ddd ;
36+ padding : 0px ;
37+ }
38+
39+ .media-object {
40+ max-width : 64px ;
41+ }
42+
43+ .current-chat {
44+ height : 100vh ;
45+ border : 1px solid # ddd ;
46+ }
47+
48+ .current-chat-area {
49+ padding-top : 10px ;
50+ overflow : auto;
51+ height : 92vh ;
52+ }
53+
54+ .chat-input {
55+ margin-top : 10px ;
56+ margin-bottom : 10px ;
57+ height : 8vh ;
58+ }
59+
60+ .chat-input textarea {
61+ width : 100% ;
62+ border : none;
63+ }
64+ .chat-input button {
65+ position : absolute;
66+ right : 10px ;
67+ }
68+ </ style >
69+ </ head >
70+ < body >
71+ < div class ="container-fluid ">
72+ < div class ="row ">
73+ < div class ="col-md-12 current-chat ">
74+ < div class ="row current-chat-area ">
75+ < div class ="col-md-12 ">
76+ < ul class ="media-list ">
77+ < li th:each ="message : ${messages} " class ="media ">
78+ < div class ="media-body ">
79+ < div class ="media ">
80+ < a class ="pull-left " href ="# ">
81+ < img class ="media-object img-circle "
82+ th:src ="${message.getUser().getAvatarImageLink()} "/>
83+ </ a >
84+ < div class ="media-body " th:inline ="none ">
85+ < span th:utext ="${message.getContent()} " th:remove ="tag "> title</ span >
86+ < br />
87+ < small class ="text-muted "
88+ th:text ="${message.getUser().getName()
89+ + ' | '
90+ + #temporals.format(message.getSent(), 'dd-MM-yyyy, HH:mm:ss')} "> </ small >
91+ < hr />
92+ </ div >
93+ </ div >
94+ </ div >
95+ </ li >
96+ </ ul >
97+ </ div >
98+ </ div >
99+ < div class ="row chat-input ">
100+ < div class ="col-sm-12 ">
101+ < textarea class ="write_msg " placeholder ="Type a message "> </ textarea >
102+ < button class ="msg_send_btn " type ="button "> < i class ="fa fa-paper-plane-o " aria-hidden ="true "> </ i > </ button >
103+ </ div >
104+ </ div >
105+ </ div >
106+ </ div >
107+ </ div >
108+ < script th:inline ="javascript ">
109+ /*<![CDATA[*/
110+ var messageTemplate = _ . template (
111+ '<li class="media">'
112+ + '<div class="media-body">'
113+ + '' + '<div class="media">'
114+ + '' + '' + '<a class="pull-left" href="#">'
115+ + '' + '' + '' + '<img class="media-object img-circle" src="<%= user.avatarImageLink %>"/>'
116+ + '' + '' + '</a>'
117+ + '' + '' + '<div class="media-body">'
118+ + '' + '' + '' + '<%= content %>'
119+ + '' + '' + '' + '<br/>'
120+ + '' + '' + '' + '<small class="text-muted"><%= user.name %> | <%= moment(sent).format("DD-MM-YYYY, HH:mm:ss") %></small>'
121+ + '' + '' + '' + '<hr/>'
122+ + '' + '' + '</div>'
123+ + '' + '</div>'
124+ + '</div>' +
125+ '</li>' ,
126+ { 'imports' : { 'moment' : moment } } ) ;
127+
128+ var user = { } ;
129+ $ . ajax ( {
130+ url : 'https://randomuser.me/api/' ,
131+ dataType : 'json' ,
132+ success : function ( data ) {
133+ user . name = data . results [ 0 ] . name . first + " " + data . results [ 0 ] . name . last ;
134+ user . avatarImageLink = data . results [ 0 ] . picture . large ;
135+ }
136+ } ) ;
137+ var lastMessageId = /*[[${lastMessageId}]]*/ '' ;
138+ var mediaList = $ ( '.media-list' ) ;
139+ var chatArea = $ ( '.current-chat-area' ) ;
140+ var messageButton = $ ( '.chat-input button' ) ;
141+ var messageInput = $ ( '.chat-input textarea' ) ;
142+
143+ chatArea . animate ( { scrollTop : mediaList . height ( ) } , 1 ) ;
144+
145+ const client = new rsocketCore . RSocketClient ( {
146+ transport : new rsocketWebSocketClient (
147+ {
148+ url : 'ws://localhost:8080/rsocket' ,
149+ } ,
150+ rsocketCore . BufferEncoders ,
151+ ) ,
152+ setup : {
153+ dataMimeType : 'application/json' ,
154+ metadataMimeType : rsocketCore . MESSAGE_RSOCKET_COMPOSITE_METADATA . string ,
155+ keepAlive : 5000 ,
156+ lifetime : 60000 ,
157+ } ,
158+ } ) ;
159+
160+ client . connect ( )
161+ . then ( rsocket => {
162+ var endpoint = "api.v1.messages.stream" ;
163+
164+ rsocket . requestChannel ( new rsocketFlowable . Flowable ( source => {
165+ console . log ( "channel" )
166+ source . onSubscribe ( {
167+ cancel : ( ) => { } ,
168+ request : ( n ) => { }
169+ } )
170+ messageButton . on ( "click" , function ( ) {
171+ var content = messageInput . val ( ) ;
172+ messageInput . val ( "" ) ;
173+ if ( content ) {
174+ source . onNext ( {
175+ data : Buffer . from ( JSON . stringify ( { content : content , user : user , sent : new Date ( ) . toISOString ( ) } ) ) ,
176+ metadata : rsocketCore . encodeAndAddWellKnownMetadata (
177+ Buffer . alloc ( 0 ) ,
178+ rsocketCore . MESSAGE_RSOCKET_ROUTING ,
179+ Buffer . from ( String . fromCharCode ( endpoint . length ) + endpoint )
180+ )
181+ } ) ;
182+ }
183+ } ) ;
184+ } ) )
185+ . subscribe ( {
186+ onSubscribe : ( s ) => {
187+ s . request ( 1000 )
188+ }
189+ } ) ;
190+
191+ rsocket . requestStream ( {
192+ metadata : rsocketCore . encodeAndAddWellKnownMetadata (
193+ Buffer . alloc ( 0 ) ,
194+ rsocketCore . MESSAGE_RSOCKET_ROUTING ,
195+ Buffer . from ( String . fromCharCode ( endpoint . length ) + endpoint )
196+ )
197+ } )
198+ . subscribe ( {
199+ onSubscribe : ( s ) => {
200+ s . request ( 1000 )
201+ } ,
202+ onNext : ( e ) => {
203+ var v = JSON . parse ( e . data ) ;
204+
205+ mediaList . append ( messageTemplate ( v ) ) ;
206+ chatArea . stop ( ) ;
207+ chatArea . animate ( { scrollTop : mediaList . height ( ) } , 500 ) ;
208+ }
209+ } ) ;
210+ } ) ;
211+
212+ /*]]>*/
213+ </ script >
214+ </ body >
215+ </ html >
0 commit comments