diff --git a/index.html b/index.html index 3014cb3..eed8428 100644 --- a/index.html +++ b/index.html @@ -4,15 +4,15 @@ - + -

Hester Gomez

-

(Luna, )

- - - +

Hester is typing...

+
diff --git a/main.js b/main.js index 1d10988..a6fbab2 100644 --- a/main.js +++ b/main.js @@ -26,8 +26,9 @@ conversation = [ { c: 1, text: ":)"} ]; +sentMessages = [] let messageIdx = 1; -let title = "hester"; +let title = "Hester Gomez"; let pings = 0; function getMessageList() { @@ -41,17 +42,17 @@ function getMessageElement(messageIdx) { } class SentMessage { - constructor(oneWayLag, idx) { + constructor(oneWayLag, idx, onDelivered) { this.oneWayLag = oneWayLag; this.idx = idx; - //this.content = conversation[idx].text; this.createdTime = Date.now(); + this.onDelivered = onDelivered; this.updateBarIntervalId = setInterval(() => { let elapsed = Math.abs(Date.now() - this.createdTime) / 1000; let progress = elapsed / this.oneWayLag; - // divide in half so we measure the round trip + // divide in half to measure the round trip progress /= 2; this.setProgress(progress); @@ -77,11 +78,11 @@ class SentMessage { this.updateStatus("delivered"); clearInterval(this.updateBarIntervalId); amount = 0; + this.onDelivered(); } amount = Math.min(amount, 1); let percentage = `${amount * 100}%`; progressBar.style.width = percentage; - } updateStatus(newStatus) { @@ -95,23 +96,17 @@ function updateTextBox(message) { document.getElementById("textbox-input").value = message; } -// show messages up to index -function showMessages(idx) { +function setTypingIndicator(isTyping) { + document.getElementById("typing-indicator").innerHTML = isTyping + ? "Hester is typing..." + : ""; +} - let messageList = getMessageList(); - - // TODO: rebuilding the DOM here clears this status of sent messages. instead of - // rebuilding it completely, append a new message onto the end of the inner html. - // TODO: is this also the juncture to clear the status of previous messages? - - // clear current messages - messageList.innerHTML = ""; - - // inject messages into ul - for (let i = 0; i < idx; i++) { - let message = conversation[i]; - messageList.innerHTML += getMessageHtml(message.text, isMessageOurs(message)); - } +// add the message at the index to the displayed messages +function addMessage(idx) { + let message = conversation[idx]; + let messageHtml = getMessageHtml(message.text, isMessageOurs(message)); + getMessageList().innerHTML += messageHtml; } function getMessageHtml(text, isOurs) { @@ -187,29 +182,45 @@ function getResponses(idx) { } function updateChat(messageIdx) { - showMessages(messageIdx); + addMessage(messageIdx-1); updatePreviewText(messageIdx); updatePings(); } +function getRandomDelay(min, max) { + const range = max - min; + return min + Math.random() * range; +} + function waitForIncomingMessages() { // we don't want messages to arrive all at once if there are multiple messages, // so we need to add a small delay to consecutive messages and wait for them one by one - let smallDelay = 2; + let smallDelay = getRandomDelay(2, 10); let responses = getResponses(messageIdx); let lightLag = getLightLag(); - for (let i = 0; i < responses.length; i++) { - let delaySeconds = lightLag + smallDelay * i; + setTimeout(() => { + setTypingIndicator(true); - setTimeout(() => { - messageIdx++; - pings++; + for (let i = 0; i < responses.length; i++) { + let delaySeconds = lightLag + smallDelay * i; - // update the chat with their message - updateChat(messageIdx); - }, delaySeconds * 1000); - } + const stopTyping = i == responses.length - 1; + + setTimeout(() => { + messageIdx++; + pings++; + + // update the chat with their message + updateChat(messageIdx); + + if (stopTyping) { + setTypingIndicator(false); + } + + }, delaySeconds * 1000); + } + },getRandomDelay(1, 3)); } function updatePreviewText(messageIdx) { @@ -226,24 +237,37 @@ function sendOurMessage() { // before advancing the conversation let oneWayLag = getLightLag(); let currentMessage = conversation[messageIdx]; - let sentMessage = new SentMessage(oneWayLag, messageIdx); - console.log(sentMessage); + let nextMessage = conversation[messageIdx + 1]; - // message.send() - // when we send the message, we want to start an interval that updates the progress animation - // message.setProgress() should be a private method that updates the appropriate element + let sentMessage = new SentMessage(oneWayLag, messageIdx, () => { + + // if the next message is ours we don't need to wait for anything + if (isMessageOurs(nextMessage)) + return; + + // wait for them to read the message + setTimeout(() => { + // set the message status to read + sentMessage.updateStatus("read"); + + // hide the status of previous messages we first need to have references to all of them + // when creating messages we need to add these too an array + for (let i = 0; i < sentMessages.length; i++) { + let message = sentMessages[i]; + if (message != sentMessage) { + message.updateStatus(""); + } + } + + waitForIncomingMessages(); + }, getRandomDelay(5, 30) * 1000); + }); + sentMessages.push(sentMessage); // advance conversation with our next message messageIdx++; - nextMessage = conversation[messageIdx]; - - // if the next message is not ours, we need to wait for it: set off a thread that - // will update the message index and the displayed messages in a few seconds - // we are still waiting to receive messages so pressing the button oughtn't do anything - if (!isMessageOurs(nextMessage)) { - waitForIncomingMessages(); - } + // update displayed messages updateChat(messageIdx); } @@ -273,7 +297,12 @@ function startLightLagUpdateLoop() { } function init() { - showMessages(messageIdx); + setTimeout(() => { + addMessage(0); + updatePings(); + setTypingIndicator(false); + }, 400); + // load the first message into the text box updateTextBox(conversation[messageIdx].text); pings = 1; diff --git a/styles.css b/styles.css index e491f89..09f076f 100644 --- a/styles.css +++ b/styles.css @@ -2,7 +2,17 @@ html { font-family: sans-serif; } +body { + margin-left: 0; + margin-right: 0; +} + +#page { + max-width: 600px; +} + h1 { + margin-left: 0.5em; display: inline; } @@ -36,7 +46,7 @@ h1 { } ul { - margin-bottom: 1.5em; + margin: 1em; padding: 0; list-style: none; } @@ -45,18 +55,31 @@ li { height: 2.5em; width: 100%; - margin-top: 1.5em; + margin-bottom: 1.5em; position: relative; } + #textbox { - margin-top: 2em; - padding: 0; + width: 100%; + position: absolute; + bottom: 0; + + margin-top: 0.5em; +} + +#typing-indicator { + margin: 0; + margin-left: 1em; + margin-bottom: 0.5em; + + position: absolute; + bottom: 3em; } #textbox input { margin: 0.5em; - margin-left: 0; + left: 1em; width: 85%; font-size: 1em; @@ -71,16 +94,6 @@ button { font-size: 1em; } -/* -.loader-container { - display: flex; - justify-content: center; - align-items: center; - height: 100vh; -} -*/ - - .progress-bar { width: 100%; height: 100%; @@ -101,9 +114,6 @@ button { width: 0; height: 100%; background-color: #ff5c35; - /* - animation: fill 4s infinite; - */ } .message-status { @@ -113,14 +123,3 @@ button { right: 1em; font-size: .8em; } - -/* -@keyframes fill { - 0% { - width: 0; - } - 100% { - width: 100%; - } -} -*/