Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 

193 рядки
6.7 KiB

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8">
  5. <title>FastAPI Websocket Chat</title>
  6. <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
  7. <style>
  8. #main {
  9. margin-top: 4rem;
  10. }
  11. #chatbox {
  12. overflow-y: scroll;
  13. height: 40rem;
  14. }
  15. .thin-alert {
  16. padding: .25rem 1.25rem;
  17. }
  18. </style>
  19. </head>
  20. <body>
  21. <div class="container">
  22. <div id="main" class="row">
  23. <div class="col-md-9">
  24. <h4>Chat</h4>
  25. <div id="chatbox">
  26. <div id="messages"></div>
  27. </div>
  28. <form>
  29. <div class="form-group row">
  30. <label for="chat-input" class="col-sm-1 col-form-label">Message</label>
  31. <div class="col-sm-9">
  32. <input type="text" class="form-control" id="chat-input" placeholder="Enter message...">
  33. </div>
  34. <div class="col-sm-2">
  35. <button type="submit" class="btn btn-primary" disabled="disabled">Send</button>
  36. </div>
  37. </div>
  38. </form>
  39. </div>
  40. <div class="col-md-3">
  41. <h4>Connected Users</h4>
  42. <ul id="users"></ul>
  43. </div>
  44. </div>
  45. </div>
  46. <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
  47. <script>
  48. /** Add a user to the list of connected users.*/
  49. function addToUsersList(userId, isYou) {
  50. const newUserLi = $('<li id="users-list-' + userId + '"></li>');
  51. newUserLi.append(userId);
  52. if(isYou) {
  53. newUserLi.append($('<em> (you)</em>'));
  54. }
  55. $('#users').append(newUserLi);
  56. }
  57. /** Add a user to the list of connected users and print an alert.*/
  58. function addUser(userId) {
  59. console.log('Adding user to connected users list:', userId);
  60. addToUsersList(userId);
  61. addSystemMessage($('<span>User <strong>' + userId + '</strong> joined the room</span>'));
  62. }
  63. /** Remove a user from the list of connected users and print an alert.*/
  64. function removeUser(userId) {
  65. console.log('Removing user from connected users list:', userId);
  66. $('li#users-list-' + userId).remove();
  67. addSystemMessage($('<span>User <strong>' + userId + '</strong> left the room</span>'));
  68. }
  69. /** Add a new chat message from a named user. */
  70. function addChatMessage(userId, msg) {
  71. const newMessage = $('<div class="alert thin-alert" role="alert"></div>');
  72. const userSays = $('<strong>' + userId + ': </strong>');
  73. if(userId === myUserId) {
  74. newMessage.addClass('alert-secondary');
  75. } else {
  76. newMessage.addClass('alert-info');
  77. }
  78. newMessage.append(userSays);
  79. newMessage.append(msg);
  80. $('#messages').append(newMessage);
  81. }
  82. /** Add a new system message (e.g. user joined/left) to the chat. */
  83. function addSystemMessage(msg) {
  84. const newMessage = $('<div class="alert thin-alert alert-success" role="alert"></div>');
  85. newMessage.append(msg);
  86. $('#messages').append(newMessage);
  87. }
  88. /** Add a new error message to the chat. */
  89. function addErrorMessage(msg) {
  90. const newMessage = $('<div class="alert thin-alert alert-danger" role="alert"></div>');
  91. newMessage.append(msg);
  92. $('#messages').append(newMessage);
  93. }
  94. /** Handle an incoming message from the websocket connection. */
  95. function onWebsocketMessage(message) {
  96. console.log('Got message from websocket:', message);
  97. const payload = JSON.parse(message.data);
  98. switch(payload.type) {
  99. case 'MESSAGE':
  100. if(payload.data.user_id === 'server') {
  101. addSystemMessage(payload.data.msg);
  102. } else {
  103. addChatMessage(payload.data.user_id, payload.data.msg);
  104. }
  105. return;
  106. case 'USER_JOIN':
  107. addUser(payload.data);
  108. return;
  109. case 'USER_LEAVE':
  110. removeUser(payload.data);
  111. return;
  112. case 'ROOM_JOIN':
  113. myUserId = payload.data.user_id;
  114. addToUsersList(myUserId, true);
  115. return;
  116. default:
  117. throw new TypeError('Unknown message type: ' + payload.type);
  118. return;
  119. }
  120. }
  121. function onClickFactory(websocket) {
  122. return function (event) {
  123. event.preventDefault();
  124. const $messageInput = $('#chat-input');
  125. const message = $messageInput.val();
  126. $messageInput.val('');
  127. if (!message) {
  128. return
  129. }
  130. websocket.send(message);
  131. }
  132. }
  133. /** Join up the 'submit' button to the websocket interface. */
  134. function onWebsocketOpen(websocket) {
  135. console.log('Opening WebSocket connection');
  136. return function () {
  137. $('button[type="submit"]')
  138. .on('click', onClickFactory(websocket))
  139. .removeAttr('disabled');
  140. }
  141. }
  142. /** Print websocket errors into the chat box using addErrorMessage. */
  143. function onWebsocketError(err) {
  144. console.error('Websocket error: ', err);
  145. addErrorMessage('Error:' + err, 'error');
  146. onWebsocketClose();
  147. }
  148. /** Disable the 'submit' button when the websocket connection closes. */
  149. function onWebsocketClose() {
  150. console.log('Closing WebSocket connection');
  151. $('button[type="submit"]')
  152. .off('click')
  153. .attr('disabled', 'disabled');
  154. }
  155. /** On page load, open a websocket connection, and fetch the list of active users. */
  156. $(function() {
  157. function reqListener () {
  158. const userData = JSON.parse(this.responseText);
  159. console.log('Received user list:', userData);
  160. userData.users.forEach(addToUsersList);
  161. $(function() {
  162. let myUserId = null;
  163. websocket = new WebSocket('ws://192.168.60.33:5050/ws');
  164. websocket.onopen = onWebsocketOpen(websocket);
  165. websocket.onerror = onWebsocketError;
  166. websocket.onclose = onWebsocketClose;
  167. websocket.onmessage = onWebsocketMessage;
  168. });
  169. }
  170. const oReq = new XMLHttpRequest();
  171. oReq.addEventListener("load", reqListener);
  172. oReq.open("GET", "http://192.168.60.33:5050/list_users");
  173. oReq.send();
  174. });
  175. </script>
  176. </body>
  177. </html>