Add the CSS to amek this work, log better in the app

This commit is contained in:
Dave Smith-Hayes 2024-10-28 21:47:30 -04:00
parent 8b55e01bfa
commit add5c2f654
5 changed files with 88 additions and 62 deletions

View File

@ -50,18 +50,27 @@ function sendMessage(e) {
const MessageInput = { const MessageInput = {
view: function () { view: function () {
return m("div.chat-input", [ return m("div.chat-input", [
m("form", { method: "post", onsubmit: sendMessage }, [ m("form", { method: "post", onsubmit: this.handleSubmit }, [
m("input", { name: "chatter", placeholder: "Name" }), m("input", { name: "chatter", placeholder: "Name" }),
m("input", { name: "message", placeholder: "Message", id: "message", required: true }), m("input", { name: "message", placeholder: "Message", id: "message", required: true }),
m("input", { type: "submit", value: "Send" }) m("input", { type: "submit", value: "Send" })
]) ])
]); ]);
},
nameHidden: false,
handleSubmit: function (e) {
sendMessage(e);
if (!this.nameHidden) {
const chatterInput = document.querySelector('input[name="chatter"]')
chatterInput.setAttribute('style', 'display: none');
this.nameHidden = true;
}
} }
}; };
const Chat = { const Chat = {
view: function(vnode) { view: function(vnode) {
return m("div", [ return m("div", { class: 'container' }, [
m(MessageBox), m(MessageBox),
m(MessageInput) m(MessageInput)
]) ])

View File

@ -14,16 +14,15 @@ const { upgradeWebSocket, websocket } = createBunWebSocket<ServerWebSocket>();
app.get("/chat-service", upgradeWebSocket((c) => { app.get("/chat-service", upgradeWebSocket((c) => {
return { return {
onOpen(event, ws) { onOpen(event, ws) {
console.log(`Connection established from ${ws.raw.remoteAddress}`); console.log(JSON.stringify({ message: `Connection established`, remoteHost: ws.raw.remoteAddress }));
chatRoom.addListener('message-added', async function (e) { chatRoom.addListener('message-added', function (e) {
const message = JSON.stringify({ const message = JSON.stringify({
message: e.message.message, message: e.message.message,
chatter: e.message.chatter, chatter: e.message.chatter,
timestamp: e.message.timestamp timestamp: e.message.timestamp
}); });
console.log(message);
ws.send(message); ws.send(message);
}); });
}, },
@ -33,12 +32,13 @@ app.get("/chat-service", upgradeWebSocket((c) => {
message.timestamp = Date.now() as string; message.timestamp = Date.now() as string;
chatRoom.addMessage(message); chatRoom.addMessage(message);
console.log(JSON.stringify(message));
}, },
onClose() { onClose() {
console.log("Connection closed."); console.log(JSON.stringify({ message: `Connection closed.` }));
}, },
onError(event, ws) { onError(event, ws) {
console.error(event); console.error(JSON.stringify({ event }));
ws.close(); ws.close();
} }
} }
@ -55,4 +55,4 @@ Bun.serve({
websocket websocket
}); });
console.log(`Chat is running on ${process.env.APP_PORT}`); console.log(JSON.stringify({ message: `Chat is running`, port: process.env.APP_PORT}));

View File

@ -9,12 +9,19 @@ div {
box-sizing: border-box; box-sizing: border-box;
} }
.container {
display: flex;
flex-direction: column;
height: 100vh;
}
.messages { .messages {
padding: 1em; padding: 1em;
display: flex; display: flex;
flex-direction: column-reverse; flex-direction: column-reverse;
height: auto; flex-grow: 1;
overflow: auto; overflow: auto;
position: relative;
} }
.messages .message { .messages .message {
@ -33,14 +40,12 @@ div {
} }
.chat-input { .chat-input {
position: fixed;
bottom: 0;
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
border-top: 1px solid #ccc; border-top: 1px solid #ccc;
height: auto;
padding: 1em; padding: 1em;
background-color: #f4efe6; background-color: #f4efe6;
align-self: flex-end;
} }
.chat-input > form { .chat-input > form {
display: flex; display: flex;
@ -51,6 +56,8 @@ div {
.chat-input > form > submit { .chat-input > form > submit {
padding: 1em 1.25em; padding: 1em 1.25em;
margin-right: 1em; margin-right: 1em;
box-sizing: border-box;
font-famil: monospace !important;
} }
.chat-input > form > submit { .chat-input > form > submit {
background-color: #020a03; background-color: #020a03;
@ -58,7 +65,6 @@ div {
border-radius: 5px; border-radius: 5px;
color: #fffbf6; color: #fffbf6;
font-weight: bold; font-weight: bold;
font-family: monospace !important;
padding: 0.75em 1em; padding: 0.75em 1em;
margin-right: 0; margin-right: 0;
} }
@ -67,47 +73,48 @@ div {
border: 1px solid #020a03; border: 1px solid #020a03;
border-radius: 5px; border-radius: 5px;
color: #0c0b09; color: #0c0b09;
font-family: monospace;
} }
.chat-input > form > input[name="message"] { .chat-input > form > input[name="message"] {
width: 75%; width: 75%;
border: 1px solid #020a03; border: 1px solid #020a03;
border-radius: 5px; border-radius: 5px;
color: #0c0b09; color: #0c0b09;
font-family: monospace;
} }
@media only screen and (max-width: 600px) { @media only screen and (max-width: 600px) {
.chat-input { .chat-input {
padding: 2.5em; padding: 1em;
} }
.chat-input > form { .chat-input > form {
display: flex; display: flex;
flex-wrap: wrap;
width: 100%; width: 100%;
box-sizing: border-box; box-sizing: border-box;
flex-direction: column; }
.chat-input > form > input,
.chat-input > form > submit {
box-sizing: border-box;
margin: 0.25em;
font-size: 1em;
padding: 0.75em 1em;
border-radius: 0.25em;
width: 100%;
} }
.chat-input > form > input[name="chatter"] { .chat-input > form > input[name="chatter"] {
width: 100%; width: 100%;
font-size: 3.5em; order: 1;
margin-bottom: 0.5em;
box-sizing: border-box;
} }
.chat-input > form > input[name="message"] { .chat-input > form > input[name="message"] {
width: 100%; width: 60%;
font-size: 3.5em; order: 2;
margin-bottom: 0.5em;
box-sizing: border-box;
} }
.chat-input > form > input[type=submit] {
.chat-input > form > input, .chat-input > form > submit { width: 34%;
padding: 0.75em 1em; order: 3;
border-radius: 0.25em;
width: 100%;
font-size: 3.5em;
} }
} }

View File

@ -2,6 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<title>A Dumb Chat Application</title> <title>A Dumb Chat Application</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="/css/main.css" /> <link rel="stylesheet" type="text/css" href="/css/main.css" />
</head> </head>
<body> <body>

View File

@ -79,11 +79,6 @@ var require_hasOwn = __commonJS((exports, module) => {
// node_modules/mithril/render/hyperscript.js // node_modules/mithril/render/hyperscript.js
var require_hyperscript = __commonJS((exports, module) => { var require_hyperscript = __commonJS((exports, module) => {
var Vnode = require_vnode();
var hyperscriptVnode = require_hyperscriptVnode();
var hasOwn = require_hasOwn();
var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g;
var selectorCache = {};
function isEmpty(object) { function isEmpty(object) {
for (var key in object) for (var key in object)
if (hasOwn.call(object, key)) if (hasOwn.call(object, key))
@ -152,6 +147,11 @@ var require_hyperscript = __commonJS((exports, module) => {
vnode.tag = selector; vnode.tag = selector;
return vnode; return vnode;
} }
var Vnode = require_vnode();
var hyperscriptVnode = require_hyperscriptVnode();
var hasOwn = require_hasOwn();
var selectorParser = /(?:(^|#|\.)([^#\.\[\]]+))|(\[(.+?)(?:\s*=\s*("|'|)((?:\\["'\]]|.)*?)\5)?\])/g;
var selectorCache = {};
module.exports = hyperscript; module.exports = hyperscript;
}); });
@ -187,7 +187,6 @@ var require_hyperscript2 = __commonJS((exports, module) => {
// node_modules/mithril/render/domFor.js // node_modules/mithril/render/domFor.js
var require_domFor = __commonJS((exports, module) => { var require_domFor = __commonJS((exports, module) => {
var delayedRemoval = new WeakMap;
function* domFor({ dom, domSize }, { generation } = {}) { function* domFor({ dom, domSize }, { generation } = {}) {
if (dom != null) if (dom != null)
do { do {
@ -199,6 +198,7 @@ var require_domFor = __commonJS((exports, module) => {
dom = nextSibling; dom = nextSibling;
} while (domSize); } while (domSize);
} }
var delayedRemoval = new WeakMap;
module.exports = { module.exports = {
delayedRemoval, delayedRemoval,
domFor domFor
@ -1480,6 +1480,13 @@ var require_censor = __commonJS((exports, module) => {
// node_modules/mithril/api/router.js // node_modules/mithril/api/router.js
var require_router = __commonJS((exports, module) => { var require_router = __commonJS((exports, module) => {
function decodeURIComponentSave(component) {
try {
return decodeURIComponent(component);
} catch (e) {
return component;
}
}
var Vnode = require_vnode(); var Vnode = require_vnode();
var m = require_hyperscript(); var m = require_hyperscript();
var buildPathname = require_build2(); var buildPathname = require_build2();
@ -1488,13 +1495,6 @@ var require_router = __commonJS((exports, module) => {
var assign = require_assign(); var assign = require_assign();
var censor = require_censor(); var censor = require_censor();
var sentinel = {}; var sentinel = {};
function decodeURIComponentSave(component) {
try {
return decodeURIComponent(component);
} catch (e) {
return component;
}
}
module.exports = function($window, mountRedraw) { module.exports = function($window, mountRedraw) {
var callAsync = $window == null ? null : typeof $window.setImmediate === "function" ? $window.setImmediate : $window.setTimeout; var callAsync = $window == null ? null : typeof $window.setImmediate === "function" ? $window.setImmediate : $window.setTimeout;
var p = Promise.resolve(); var p = Promise.resolve();
@ -1721,34 +1721,18 @@ var import_mithril = __toESM(require_mithril(), 1);
// frontend/websocket.js // frontend/websocket.js
function createWebSocket() { function createWebSocket() {
let appUrl = "chat.freedoom.party"; let appUrl = "localhost:3000";
appUrl = `//${appUrl}/chat-service`; appUrl = `//${appUrl}/chat-service`;
return new WebSocket(appUrl); return new WebSocket(appUrl);
} }
// frontend/index.js // frontend/index.js
var messages = [];
var socket = createWebSocket();
socket.onmessage = function(event) {
if (event.type === "message") {
const message = JSON.parse(event.data);
messages.push(message);
import_mithril.default.redraw();
}
};
function newMessageText(name, message) { function newMessageText(name, message) {
return [ return [
import_mithril.default("span.chatter", name + ": "), import_mithril.default("span.chatter", name + ": "),
import_mithril.default("span.chatter-message", message) import_mithril.default("span.chatter-message", message)
]; ];
} }
var MessageBox = {
view: function() {
return import_mithril.default(".messages", { id: "message-box" }, messages.reverse().map(function(message) {
return import_mithril.default(".message", newMessageText(message.chatter, message.message));
}), import_mithril.default("#anchor"));
}
};
function clearMessageInputBox() { function clearMessageInputBox() {
const messageBox = document.getElementById("message"); const messageBox = document.getElementById("message");
messageBox.value = ""; messageBox.value = "";
@ -1763,20 +1747,45 @@ function sendMessage(e) {
socket.send(JSON.stringify(message)); socket.send(JSON.stringify(message));
clearMessageInputBox(); clearMessageInputBox();
} }
var messages = [];
var socket = createWebSocket();
socket.onmessage = function(event) {
if (event.type === "message") {
const message = JSON.parse(event.data);
messages.push(message);
import_mithril.default.redraw();
}
};
var MessageBox = {
view: function() {
return import_mithril.default(".messages", { id: "message-box" }, messages.reverse().map(function(message) {
return import_mithril.default(".message", newMessageText(message.chatter, message.message));
}), import_mithril.default("#anchor"));
}
};
var MessageInput = { var MessageInput = {
view: function() { view: function() {
return import_mithril.default("div.chat-input", [ return import_mithril.default("div.chat-input", [
import_mithril.default("form", { method: "post", onsubmit: sendMessage }, [ import_mithril.default("form", { method: "post", onsubmit: this.handleSubmit }, [
import_mithril.default("input", { name: "chatter", placeholder: "Name" }), import_mithril.default("input", { name: "chatter", placeholder: "Name" }),
import_mithril.default("input", { name: "message", placeholder: "Message", id: "message", required: true }), import_mithril.default("input", { name: "message", placeholder: "Message", id: "message", required: true }),
import_mithril.default("input", { type: "submit", value: "Send" }) import_mithril.default("input", { type: "submit", value: "Send" })
]) ])
]); ]);
},
nameHidden: false,
handleSubmit: function(e) {
sendMessage(e);
if (!this.nameHidden) {
const chatterInput = document.querySelector('input[name="chatter"]');
chatterInput.setAttribute("style", "display: none");
this.nameHidden = true;
}
} }
}; };
var Chat = { var Chat = {
view: function(vnode) { view: function(vnode) {
return import_mithril.default("div", [ return import_mithril.default("div", { class: "container" }, [
import_mithril.default(MessageBox), import_mithril.default(MessageBox),
import_mithril.default(MessageInput) import_mithril.default(MessageInput)
]); ]);