From f4815e331cad0db78220173060dafdf19b09faf4 Mon Sep 17 00:00:00 2001 From: Gabe Kangas Date: Fri, 16 Oct 2020 17:36:11 -0700 Subject: [PATCH] Update chat styling --- test/userColorsTest.js | 27 ++++- webroot/js/components/chat/message.js | 145 ++------------------------ webroot/js/utils/chat.js | 1 - webroot/js/utils/user-colors.js | 22 +++- webroot/js/utils/websocket.js | 3 +- 5 files changed, 49 insertions(+), 149 deletions(-) diff --git a/test/userColorsTest.js b/test/userColorsTest.js index 1dcfaac32..7b8d39f55 100644 --- a/test/userColorsTest.js +++ b/test/userColorsTest.js @@ -11,8 +11,9 @@ for (var i = 0; i < 20; i++) { console.log(``); function generateElement(string) { - const color = messageBubbleColorForString(string); - return `
${string}
` + const bgColor = messageBubbleColorForString(string); + const fgColor = textColorForString(string); + return `
${string}
`; } function randomString(length) { @@ -27,9 +28,25 @@ function messageBubbleColorForString(str) { } // Tweak these to adjust the result of the color - const saturation = 75; - const lightness = 65; - const alpha = 1.0; + const saturation = 25; + const lightness = 45; + const alpha = 0.3; + const hue = parseInt(Math.abs(hash), 16) % 360; + + return `hsla(${hue}, ${saturation}%, ${lightness}%, ${alpha})`; +} + +function textColorForString(str) { + let hash = 0; + for (let i = 0; i < str.length; i++) { + // eslint-disable-next-line + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + + // Tweak these to adjust the result of the color + const saturation = 80; + const lightness = 80; + const alpha = 0.8; const hue = parseInt(Math.abs(hash), 16) % 360; return `hsla(${hue}, ${saturation}%, ${lightness}%, ${alpha})`; diff --git a/webroot/js/components/chat/message.js b/webroot/js/components/chat/message.js index 7ca63e1b3..e0fbf21f9 100644 --- a/webroot/js/components/chat/message.js +++ b/webroot/js/components/chat/message.js @@ -2,38 +2,17 @@ import { h, Component } from '/js/web_modules/preact.js'; import htm from '/js/web_modules/htm.js'; const html = htm.bind(h); +import ChatMessageView from './chat-message-view.js'; + import { messageBubbleColorForString } from '../../utils/user-colors.js'; -import { convertToText } from '../../utils/chat.js'; import { SOCKET_MESSAGE_TYPES } from '../../utils/websocket.js'; export default class Message extends Component { render(props) { - const { message, username } = props; + const { message } = props; const { type } = message; - if (type === SOCKET_MESSAGE_TYPES.CHAT) { - const { author, body, timestamp } = message; - const formattedMessage = formatMessageText(body, username); - const formattedTimestamp = formatTimestamp(timestamp); - - const authorColor = messageBubbleColorForString(author); - const authorTextColor = { color: authorColor }; - return ( - html` -
-
-
- ${author} -
-
-
-
- `); + if (type === SOCKET_MESSAGE_TYPES.CHAT || type === SOCKET_MESSAGE_TYPES.SYSTEM) { + return html`<${ChatMessageView} ...${props} />`; } else if (type === SOCKET_MESSAGE_TYPES.NAME_CHANGE) { const { oldName, newName } = message; return ( @@ -47,121 +26,9 @@ export default class Message extends Component { ` ); - } - } -} - -export function formatMessageText(message, username) { - let formattedText = highlightUsername(message, username); - formattedText = getMessageWithEmbeds(formattedText); - return convertToMarkup(formattedText); -} - -function highlightUsername(message, username) { - const pattern = new RegExp( - '@?' + username.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), - 'gi' - ); - return message.replace( - pattern, - '$&' - ); -} - -function getMessageWithEmbeds(message) { - var embedText = ''; - // Make a temporary element so we can actually parse the html and pull anchor tags from it. - // This is a better approach than regex. - var container = document.createElement('p'); - container.innerHTML = message; - - var anchors = container.getElementsByTagName('a'); - for (var i = 0; i < anchors.length; i++) { - const url = anchors[i].href; - if (getYoutubeIdFromURL(url)) { - const youtubeID = getYoutubeIdFromURL(url); - embedText += getYoutubeEmbedFromID(youtubeID); - } else if (url.indexOf('instagram.com/p/') > -1) { - embedText += getInstagramEmbedFromURL(url); - } else if (isImage(url)) { - embedText += getImageForURL(url); - } - } - - // If this message only consists of a single embeddable link - // then only return the embed and strip the link url from the text. - if (embedText !== '' && anchors.length == 1 && isMessageJustAnchor(message, anchors[0])) { - return embedText; - } - return message + embedText; -} - -function getYoutubeIdFromURL(url) { - try { - var regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/; - var match = url.match(regExp); - - if (match && match[2].length == 11) { - return match[2]; } else { - return null; + console.log("Unknown message type:", type); } - } catch (e) { - console.log(e); - return null; } } -function getYoutubeEmbedFromID(id) { - return `
`; -} - -function getInstagramEmbedFromURL(url) { - const urlObject = new URL(url.replace(/\/$/, '')); - urlObject.pathname += '/embed'; - return ``; -} - -function isImage(url) { - const re = /\.(jpe?g|png|gif)$/i; - return re.test(url); -} - -function getImageForURL(url) { - return ``; -} - -function isMessageJustAnchor(message, anchor) { - return stripTags(message) === stripTags(anchor.innerHTML); -} - -function formatTimestamp(sentAt) { - sentAt = new Date(sentAt); - if (isNaN(sentAt)) { - return ''; - } - - let diffInDays = (new Date() - sentAt) / (24 * 3600 * 1000); - if (diffInDays >= 1) { - return ( - `Sent at ${sentAt.toLocaleDateString('en-US', { - dateStyle: 'medium', - })} at ` + sentAt.toLocaleTimeString() - ); - } - - return `Sent at ${sentAt.toLocaleTimeString()}`; -} - -/* - You would call this when receiving a plain text - value back from an API, and before inserting the - text into the `contenteditable` area on a page. -*/ -function convertToMarkup(str = '') { - return convertToText(str).replace(/\n/g, '
'); -} - -function stripTags(str) { - return str.replace(/<\/?[^>]+(>|$)/g, ''); -} diff --git a/webroot/js/utils/chat.js b/webroot/js/utils/chat.js index 4b0af9e0e..49590c66a 100644 --- a/webroot/js/utils/chat.js +++ b/webroot/js/utils/chat.js @@ -64,7 +64,6 @@ export function extraUserNamesFromMessageHistory(messages) { return list; } - // utils from https://gist.github.com/nathansmith/86b5d4b23ed968a92fd4 /* You would call this after getting an element's diff --git a/webroot/js/utils/user-colors.js b/webroot/js/utils/user-colors.js index 70b2e4832..331db934a 100644 --- a/webroot/js/utils/user-colors.js +++ b/webroot/js/utils/user-colors.js @@ -6,9 +6,25 @@ export function messageBubbleColorForString(str) { } // Tweak these to adjust the result of the color - const saturation = 75; - const lightness = 65; - const alpha = 1.0; + const saturation = 25; + const lightness = 45; + const alpha = 0.3; + const hue = parseInt(Math.abs(hash), 16) % 360; + + return `hsla(${hue}, ${saturation}%, ${lightness}%, ${alpha})`; +} + +export function textColorForString(str) { + let hash = 0; + for (let i = 0; i < str.length; i++) { + // eslint-disable-next-line + hash = str.charCodeAt(i) + ((hash << 5) - hash); + } + + // Tweak these to adjust the result of the color + const saturation = 80; + const lightness = 80; + const alpha = 0.8; const hue = parseInt(Math.abs(hash), 16) % 360; return `hsla(${hue}, ${saturation}%, ${lightness}%, ${alpha})`; diff --git a/webroot/js/utils/websocket.js b/webroot/js/utils/websocket.js index 893f552ea..32dd74515 100644 --- a/webroot/js/utils/websocket.js +++ b/webroot/js/utils/websocket.js @@ -7,7 +7,8 @@ export const SOCKET_MESSAGE_TYPES = { CHAT: 'CHAT', PING: 'PING', NAME_CHANGE: 'NAME_CHANGE', - PONG: 'PONG' + PONG: 'PONG', + SYSTEM: 'SYSTEM' }; export const CALLBACKS = {