index.html 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. <!-- COPYRIGHT (C) AMY <RAIN@SKULD.NETWORK> & IDK THIS IS MOSTLY WRITTEN WITH COPILOT LOL -->
  2. <!DOCTYPE html>
  3. <html lang="en">
  4. <head>
  5. <meta charset="UTF-8">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Chatroom</title>
  8. <style>
  9. :root {
  10. --col-1: #2f3136;
  11. --col-2: #36393f;
  12. --col-3: #40444b;
  13. --col-accent: #7289da;
  14. --col-text-1: rgb(200, 200, 200);
  15. --col-text-2: white;
  16. }
  17. html {
  18. font-family: Arial, Helvetica, sans-serif;
  19. font-size: 1rem;
  20. background-color: var(--col-1);
  21. }
  22. body {
  23. background-color: var(--col-1);
  24. color: var(--col-text-1);
  25. height: 100vh;
  26. margin: 0;
  27. padding: 0;
  28. }
  29. .panel-host {
  30. display: flex;
  31. width: 100%;
  32. height: 100%;
  33. }
  34. .panel {
  35. display: flex;
  36. flex-direction: column;
  37. overflow-y: auto;
  38. padding: 1em;
  39. background-color: var(--col-1);
  40. border-style: solid;
  41. border-collapse: collapse;
  42. border-color: var(--col-3);
  43. border-width: 0 0.1em 0 0;
  44. }
  45. #user-list,
  46. #channel-list {
  47. flex-shrink: 0;
  48. flex-grow: 1;
  49. min-width: 15%;
  50. max-width: 15%;
  51. width: 15%;
  52. }
  53. #chat-area {
  54. flex-grow: 5;
  55. display: flex;
  56. flex-direction: column;
  57. }
  58. #messages {
  59. flex-shrink: 0;
  60. flex: 1;
  61. overflow-y: auto;
  62. display: flex;
  63. flex-direction: column-reverse;
  64. }
  65. h2 {
  66. margin: 0 0 1em 0;
  67. }
  68. button {
  69. background-color: var(--col-accent);
  70. color: var(--col-text-2);
  71. border: none;
  72. border-radius: 0.3em;
  73. padding: 0.5em;
  74. font-size: inherit;
  75. cursor: pointer;
  76. user-select: none;
  77. -webkit-user-select: none;
  78. }
  79. #textentry {
  80. display: flex;
  81. }
  82. #textentry input {
  83. font-size: inherit;
  84. width: 100%;
  85. padding: 0.5em;
  86. margin-right: 0.5em;
  87. border: none;
  88. border-radius: 0.3em;
  89. background-color: var(--col-3);
  90. color: var(--col-text-1);
  91. }
  92. .message {
  93. margin-bottom: 0.5em;
  94. }
  95. .channel-item {
  96. cursor: pointer;
  97. padding: 0.25em 0.5em;
  98. border-radius: 0.3em;
  99. margin-bottom: 0.2em;
  100. }
  101. .channel-item:hover {
  102. background-color: var(--col-3);
  103. }
  104. .channel-item.active {
  105. background-color: var(--col-accent);
  106. color: var(--col-text-2);
  107. }
  108. </style>
  109. </head>
  110. <body>
  111. <div class="panel-host" style="flex-direction: column;">
  112. <!-- <div class="panel-host">
  113. <div class="panel">
  114. <button onclick=switchTheme()>Appearance</button>
  115. </div>
  116. </div> -->
  117. <div class="panel-host">
  118. <div class="panel" id="channel-list">
  119. <h2>Channels</h2>
  120. <!-- Add channel list here -->
  121. </div>
  122. <div class="panel" id="user-list">
  123. <h2>Users</h2>
  124. <!-- Add user list here -->
  125. </div>
  126. <div class="panel" id="chat-area">
  127. <h2>Messages</h2>
  128. <div id="messages">
  129. <!-- Add messages here -->
  130. </div>
  131. <div id="textentry">
  132. <input id="message-input" type="text" placeholder="Message #channel-name">
  133. <button onclick="submitMessage()">Send</button>
  134. </div>
  135. </div>
  136. </div>
  137. </div>
  138. <script>
  139. /// (time, channel, username, content)
  140. messages = [];
  141. selectedChannel = null;
  142. function randomNumericString(length) {
  143. let v = 10 ** length;
  144. return Math.floor(Math.random() * v * 0.9 + v * 0.1);
  145. }
  146. function switchTheme() {
  147. const e = document.querySelector('body');
  148. e.setAttribute('data-theme', e.getAttribute('data-theme') === 'light' ? 'dark' : 'light');
  149. }
  150. function simulateReceivingMessages() {
  151. // Simulate receiving messages
  152. setInterval(() => {
  153. const channels = ["root", "general", "random"];
  154. const channel = channels[Math.floor(Math.random() * channels.length)];
  155. const username = `User${randomNumericString(4)}`;
  156. const message = `Hello ${channel} from ${username}!`;
  157. messages.push([Date.now(), channel, username, message]);
  158. }, 100);
  159. }
  160. function visualUpdate() {
  161. const messagesDiv = document.querySelector('#messages');
  162. messagesDiv.innerHTML = "";
  163. const visibleMessages = selectedChannel
  164. ? messages.filter(m => m[1] === selectedChannel)
  165. : messages;
  166. for (const [time, channel, username, message] of visibleMessages.slice().reverse()) {
  167. const messageDiv = document.createElement('div');
  168. messageDiv.classList.add('message');
  169. const timeString = new Date(time).toLocaleTimeString();
  170. messageDiv.textContent = `[${timeString}] ${username}: ${message}`;
  171. messagesDiv.appendChild(messageDiv);
  172. }
  173. // Update channels
  174. const channelList = document.querySelector('#channel-list');
  175. const channels = new Set(messages.map(m => m[1]));
  176. channelList.innerHTML = "<h2>Channels</h2>";
  177. const allChannelsDiv = document.createElement('div');
  178. allChannelsDiv.classList.add('channel-item');
  179. if (!selectedChannel) {
  180. allChannelsDiv.classList.add('active');
  181. }
  182. allChannelsDiv.textContent = '#all';
  183. allChannelsDiv.onclick = () => {
  184. selectedChannel = null;
  185. visualUpdate();
  186. };
  187. channelList.appendChild(allChannelsDiv);
  188. for (const channel of channels) {
  189. const channelDiv = document.createElement('div');
  190. channelDiv.classList.add('channel-item');
  191. if (channel === selectedChannel) {
  192. channelDiv.classList.add('active');
  193. }
  194. channelDiv.textContent = `#${channel}`;
  195. channelDiv.onclick = () => {
  196. selectedChannel = channel;
  197. visualUpdate();
  198. };
  199. channelList.appendChild(channelDiv);
  200. }
  201. // Update users
  202. const userList = document.querySelector('#user-list');
  203. const users = new Set(messages.map(m => m[2]));
  204. userList.innerHTML = "<h2>Users</h2>";
  205. for (const user of users) {
  206. const userDiv = document.createElement('div');
  207. userDiv.textContent = user;
  208. userList.appendChild(userDiv);
  209. }
  210. }
  211. function submitMessage() {
  212. const input = document.querySelector('#message-input');
  213. const message = input.value.trim();
  214. if (message) {
  215. messages.push([Date.now(), "root", "You", message]);
  216. input.value = '';
  217. }
  218. visualUpdate();
  219. // Scroll to bottom
  220. const messagesDiv = document.querySelector('#messages');
  221. messagesDiv.scrollTop = messagesDiv.scrollHeight;
  222. }
  223. function main() {
  224. setInterval(() => {
  225. // Don't update if user has scrolled up
  226. const messagesDiv = document.querySelector('#messages');
  227. if (messagesDiv.scrollTop + messagesDiv.clientHeight < messagesDiv.clientHeight) {
  228. return;
  229. }
  230. visualUpdate();
  231. }, 1000);
  232. }
  233. simulateReceivingMessages();
  234. main();
  235. </script>
  236. </body>
  237. </html>