diff options
Diffstat (limited to 'assets')
-rw-r--r-- | assets/css/app.css | 119 | ||||
-rw-r--r-- | assets/js/app.js | 30 | ||||
-rw-r--r-- | assets/js/chat.js | 115 |
3 files changed, 132 insertions, 132 deletions
diff --git a/assets/css/app.css b/assets/css/app.css index 2cc38b4..0bab67f 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -126,115 +126,16 @@ white-space: pre-line; } - -/* Chat css from: https://www.bootdey.com/snippets/view/card-chat-list#html */ -.chat-container { - height: 300px; - overflow-y: scroll; -} - -.chat-list { - padding: 0; - font-size: .8rem; - padding-bottom: 12px; -} - -.chat-list li { - margin-bottom: 10px; - overflow: auto; - color: #ffffff; +.circle { + width: 40px; + height: 40px; + border-radius: 50%; + display: flex; /* or inline-flex */ + align-items: center; + justify-content: center; } -.chat-list .chat-img { - float: left; - width: 48px; -} - -.chat-list .chat-img img { - -webkit-border-radius: 50px; - -moz-border-radius: 50px; - border-radius: 50px; - width: 100%; -} - -.chat-list .chat-message { - -webkit-border-radius: 50px; - -moz-border-radius: 50px; - border-radius: 50px; - background: #5a99ee; - display: inline-block; - padding: 10px 20px; - position: relative; -} - -.chat-list .chat-message:before { - content: ""; - position: absolute; - top: 15px; - width: 0; - height: 0; -} - -.chat-list .chat-message h5 { - margin: 0 0 5px 0; - font-weight: 600; - line-height: 100%; - font-size: .9rem; -} - -.chat-list .chat-message p { - line-height: 18px; - margin: 0; - padding: 0; -} - -.chat-list .chat-body { - margin-left: 20px; - float: left; - width: 70%; -} - -.chat-list .in .chat-message:before { - left: -12px; - border-bottom: 20px solid transparent; - border-right: 20px solid #5a99ee; -} - -.chat-list .out .chat-img { - float: right; -} - -.chat-list .out .chat-body { - float: right; - margin-right: 20px; - text-align: right; -} - -.chat-list .out .chat-message { - background: #fc6d4c; -} - -.chat-list .out .chat-message:before { - right: -12px; - border-bottom: 20px solid transparent; - border-left: 20px solid #fc6d4c; -} - -.card .card-header:first-child { - -webkit-border-radius: 0.3rem 0.3rem 0 0; - -moz-border-radius: 0.3rem 0.3rem 0 0; - border-radius: 0.3rem 0.3rem 0 0; -} -.card .card-header { - background: #17202b; - border: 0; - font-size: 1rem; - padding: .65rem 1rem; - position: relative; - font-weight: 600; - color: #ffffff; +.chat { + max-height: 50vh; + overflow-y: scroll; } - -.content{ - margin-top:40px; -}
\ No newline at end of file diff --git a/assets/js/app.js b/assets/js/app.js index 94780d0..92b68d1 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -1,6 +1,6 @@ // We import the CSS which is extracted to its own file by esbuild. // Remove this line if you add a your own CSS build pipeline (e.g postcss). -import "../css/app.css" +import "../css/app.css"; // If you want to use Phoenix channels, run `mix help phx.gen.channel` // to get started and then uncomment the line below. @@ -20,32 +20,32 @@ import "../css/app.css" // // Include phoenix_html to handle method=PUT/DELETE in forms and buttons. -import "phoenix_html" +import "phoenix_html"; // Establish Phoenix Socket and LiveView configuration. -import {Socket} from "phoenix" -import {LiveSocket} from "phoenix_live_view" -import topbar from "../vendor/topbar" +import {Socket} from "phoenix"; +import {LiveSocket} from "phoenix_live_view"; +import topbar from "../vendor/topbar"; -let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content") -let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}}) +let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content"); +let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}}); // Show progress bar on live navigation and form submits -topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"}) -window.addEventListener("phx:page-loading-start", info => topbar.show()) -window.addEventListener("phx:page-loading-stop", info => topbar.hide()) +topbar.config({barColors: {0: "#29d"}, shadowColor: "rgba(0, 0, 0, .3)"}); +window.addEventListener("phx:page-loading-start", info => topbar.show()); +window.addEventListener("phx:page-loading-stop", info => topbar.hide()); // connect if there are any LiveViews on the page -liveSocket.connect() +liveSocket.connect(); // expose liveSocket on window for web console debug logs and latency simulation: // >> liveSocket.enableDebug() // >> liveSocket.enableLatencySim(1000) // enabled for duration of browser session // >> liveSocket.disableLatencySim() -window.liveSocket = liveSocket +window.liveSocket = liveSocket; // Hack to remove alerts on click -Array.from(window.document.getElementsByClassName('alert')).forEach((x) => x.addEventListener('click', () => x.style.display = "none")) +Array.from(window.document.getElementsByClassName('alert')).forEach((x) => x.addEventListener('click', () => x.style.display = "none")); -import RoomChat from "./chat" +window.userSocket = new Socket("/socket", {params: {_csrf_token: csrfToken}}); +import RoomChat from "./chat"; window.RoomChat = RoomChat; -window.userSocket = new Socket("/socket", {params: {_csrf_token: csrfToken}})
\ No newline at end of file diff --git a/assets/js/chat.js b/assets/js/chat.js index 4183531..aa7f05d 100644 --- a/assets/js/chat.js +++ b/assets/js/chat.js @@ -1,11 +1,110 @@ -let RoomChat = { - connect(socket, postId) { - let channel = socket.channel(`post:${postId}`) +const gruvboxColors = [ + "#b8bb26", + "#fabd2f", + "#83a598", + "#d3869b", + "#8ec07c", + "#458588", + "#cc241d", + "#d65d0e", + "#bdae93", +]; +const generateGruvboxFromString = (string) => + gruvboxColors[Array.from(string).map((x) => x.charCodeAt(0)).reduce((a, x) => a+x, 0) % gruvboxColors.length]; + +const RoomChat = (() => { + let channel; + const connect = (socket, postId) => { + channel = socket.channel(`post:${postId}`); channel.join() - .receive("ok", resp => { console.log("Joined successfully: ", resp) }) - .receive("error", resp => { console.log("Unable to join: ", resp) }) + .receive("ok", resp => { console.log("Joined successfully: ", resp); }) + .receive("error", resp => { console.log("Unable to join: ", resp); }); return channel; - }, -} + }; + + const scrollToBottom = (element) => { + element.scrollTop = element.scrollHeight; + }; + + const appendComment = ({user, body, id, user_id, inserted_at}, element) => { + const messageElement = document.createElement("div"); + messageElement.innerHTML = ` + <div class="d-flex flex-row card border rounded m-2 align-items-center"> + <div class="m-2"> + <div class="circle" style="background:${generateGruvboxFromString(user)}">${user.charAt(0)}</div> + </div> + <div class="m-2"> + <div class="comment"> + <div class="comment-header"> + <span class="comment-username">${user}</span> + <span class="text-muted">${new Date(inserted_at).toLocaleString()}</span> + </div> + <div class="comment-body"> + ${body} + </div> + </div> + </div> + </div> + `; + element.appendChild(messageElement); + scrollToBottom(element); + }; + + const leaveChannel = () => { + if (channel) { + channel.leave(); + console.log(channel); + } + }; + + const main = (post_id) => { + leaveChannel(); + const chatWindow = document.getElementById("chat"); + window.userSocket.connect(); + channel = connect(window.userSocket, post_id); + + channel.on('shout', (comment) => { + appendComment(comment, chatWindow); + }); + + channel.on('initial-comments', ({comments}) => { + comments.forEach((comment) => { + appendComment(comment, chatWindow); + }); + scrollToBottom(chatWindow); + }); + + channel.on('join', ({ user }) => { + const joinElement = document.createElement("div"); + joinElement.innerHTML = ` + <div class="m-2 card border rounded p-2 text-muted"> + join: ${user} + </div> + `; + chatWindow.appendChild(joinElement); + scrollToBottom(chatWindow); + }); + + channel.on('left', ({ user }) => { + console.log(user, "left"); + }); + }; + + const submitForm = (e) => { + e.preventDefault(); + let message = e.target.elements.message.value; + if (message) { + channel.push("send", {body: message}); + e.target.elements.message.value = ""; + } + return false; + }; + + return { main, submitForm }; +})(); + +window.addEventListener('load', () => { + window.addEventListener('phx:initial-post', (e) => RoomChat.main(e.detail.id)); +}); -export default RoomChat;
\ No newline at end of file +export default RoomChat; |