Skip to content

Commit

Permalink
Improved ws chat example
Browse files Browse the repository at this point in the history
  • Loading branch information
andrebires committed Mar 18, 2022
1 parent b24ec89 commit 8367e03
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 97 deletions.
33 changes: 33 additions & 0 deletions examples/ws-chat/README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,35 @@
# Websocket chat

A simple chat room made with Lime.

![img.png](img.png)

## Requirements

- [Go 1.17+](https://go.dev/doc/install)
- [NPM 8.1+](https://docs.npmjs.com/getting-started/configuring-your-local-environment)

## Starting the server

Go to the `server` directory and run from the source using the command:
```bash
$ go run .
```
It will start listening for websocket connections in the 8080 port.

## Building the client
In the `client` directory, run the following command:
```bash
$ npm install
$ npm run build
```

This will compile the Javascript bundle to the `client/dist` folder.
Then go to the `client/dist` directory and open the `index.html` in your browser.
Every open instance of this page will connect as a distinct client to the server.

## References

- Chat HTML and CSS template: https://codepen.io/sajadhsm/pen/odaBdd
- Icons: https://loading.io/icon

107 changes: 47 additions & 60 deletions examples/ws-chat/client/dist/index.html
Original file line number Diff line number Diff line change
@@ -1,69 +1,56 @@
<html>
<head>
<title>Lime Chat</title>
</head>
<body>
<link rel="stylesheet" href="chat.css">

<section class="msger">
<header class="msger-header">
<div class="msger-header-title">
<i class="fas fa-comment-alt"></i> Lime Chat
</div>
<div class="msger-header-options">
<span><i class="fas fa-cog"></i></span>
</div>
</header>

<main class="msger-chat">
<div class="msg left-msg">
<div
class="msg-img"
style="background-image: url(https://image.flaticon.com/icons/svg/327/327779.svg)"
></div>

<div class="msg-bubble">
<div class="msg-info">
<div class="msg-info-name">BOT</div>
<div class="msg-info-time">00:00</div>
</div>

<div class="msg-text">
Hello, welcome to Lime Chat!<br><br>
The available commands are:<br><br>
<ul>
<li>
<strong>/name [new_nickname]</strong>: Sets a new nickname
</li>
<li>
<strong>/to [nickname] [message]</strong>: Sends a message exclusively to a nickname
</li>
</ul>
<link rel="stylesheet" href="chat.css">
<section class="msger">
<header class="msger-header">
<div class="msger-header-title">
<i class="fas fa-comment-alt"></i> Lime Chat
</div>
<div class="msger-header-options">
<span><i class="fas fa-cog"></i></span>
</div>
</header>

<main class="msger-chat">
<div class="msg left-msg">
<div
class="msg-img"
style="background-image: url(../images/bot.png)"
></div>

<div class="msg-bubble">
<div class="msg-info">
<div class="msg-info-name">BOT</div>
</div>

<div class="msg-text">
Hello, welcome to Lime Chat!<br><br>
The available commands are:<br><br>
<ul>
<li>
<strong>/name [new_nickname]</strong>: Sets a new nickname
</li>
<li>
<strong>/to [nickname] [message]</strong>: Sends a private message to a nickname
</li>
</ul>
</div>
</div>
</div>
</div>

<div class="msg right-msg">
<!-- <div-->
<!-- class="msg-img"-->
<!-- style="background-image: url(https://image.flaticon.com/icons/svg/145/145867.svg)"-->
<!-- ></div>-->
<div class="msg right-msg">

<!-- <div class="msg-bubble">-->
<!-- <div class="msg-info">-->
<!-- <div class="msg-info-name">Sajad</div>-->
<!-- <div class="msg-info-time">12:46</div>-->
<!-- </div>-->

<!-- <div class="msg-text">-->
<!-- You can change your name in JS section!-->
<!-- </div>-->
<!-- </div>-->
</div>
</main>
</div>
</main>

<form class="msger-inputarea">
<input type="text" class="msger-input" placeholder="Enter your message...">
<button type="submit" class="msger-send-btn">Send</button>
</form>
</section>
<form class="msger-inputarea">
<input type="text" class="msger-input" placeholder="Enter your message...">
<button type="submit" class="msger-send-btn">Send</button>
</form>
</section>
<script src="main.js"></script>
</body>
</body>
</html>
Binary file added examples/ws-chat/client/images/bot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added examples/ws-chat/client/images/person.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
103 changes: 75 additions & 28 deletions examples/ws-chat/client/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,50 @@ const msgerChat = get(".msger-chat");
const msgerButton = get(".msger-send-btn");

// Icons made by Freepik from www.flaticon.com
const PERSON_IMG = "https://image.flaticon.com/icons/svg/145/145867.svg";

let nickname = "Anonymous";
const PERSON_IMG = "../images/person.png";
const BOT_IMG = "../images/bot.png";

let nickname = `guest`;
let client = await createClient();

// Notify other users
await client.sendMessage({
id: uuidv4(),
from: nickname,
type: 'application/x-chat-joined+json',
content: {},
});

let client = await connect();
client.transport.onError = async function () {
client = await connect();
}
client.onMessage = (message) => {
switch (message.type) {
case 'application/x-chat-nickname+json':
appendMessage("BOT", PERSON_IMG, "left", `The user <strong>${message.content.old}</strong> has changed its nickname to <strong>${message.content.new}</strong>.`);
break;

default:
appendMessage(message.from, PERSON_IMG, "left", message.content);
break;
async function createClient() {
setInputEnabled(false);
try {
let client = await connect();
nickname = client.localNode.split("/")[0].split("@")[0];
client.transport.onError = async function () {
client = await connect();
}
client.onMessage = (message) => {
switch (message.type) {
case 'application/x-chat-nickname+json':
appendMessage("BOT", BOT_IMG, "left", `The user <strong>${message.content.old}</strong> has changed its nickname to <strong>${message.content.new}</strong>.`);
break;

case 'application/x-chat-joined+json':
appendMessage("BOT", BOT_IMG, "left", `The user <strong>${message.from}</strong> has joined the room.`);
break;

default:
name = message.from;
if (message.to) {
name += " (private)";
}
appendMessage(name, PERSON_IMG, "left", message.content);
break;
}
}
return client;
} finally {
setInputEnabled(true);
}
}

Expand All @@ -39,16 +66,21 @@ msgerForm.addEventListener("submit", async event => {
return;
}

await sendMessage(msgText, 'text/plain');
});

async function sendMessage(content, type, to = null) {
await client.sendMessage({
id: uuidv4(),
from: nickname,
type: 'text/plain',
content: msgText,
to: to,
type: type ?? "text/plain",
content: content,
});

appendMessage(nickname, PERSON_IMG, "right", msgText);
appendMessage(nickname, PERSON_IMG, "right", content);
msgerInput.value = "";
});
}

async function parseCommand(input) {
if (input.startsWith("/name ")) {
Expand All @@ -59,23 +91,38 @@ async function parseCommand(input) {
}
}

if (input.startsWith("/to")) {
let args = input.split(" ");
if (args.length >= 2) {
let to = args[1];
let content = args.slice(2).join(" ");
await sendMessage(content, "text/plain", to);
return true;
}
}

return false;
}

async function setNickname(newNickname) {
let oldNickname = nickname;
nickname = newNickname;

await client.sendFinishingSession();
client = await createClient();

// Notify other users
await client.sendMessage({
id: uuidv4(),
from: nickname,
type: 'application/x-chat-nickname+json',
content: {
old: nickname,
new: newNickname,
old: oldNickname,
new: nickname,
},
});

nickname = newNickname;
appendMessage("BOT", PERSON_IMG, "left", `OK! Your name now is <strong>${nickname}</strong>.`);
appendMessage("BOT", BOT_IMG, "left", `OK! Your name now is <strong>${nickname}</strong>.`);
}

function appendMessage(name, img, side, text) {
Expand Down Expand Up @@ -112,7 +159,7 @@ function formatDate(date) {
}

async function connect() {
setInputState(false);

// Creates a new transport and connect to the server
while (true) {
try {
Expand All @@ -123,12 +170,12 @@ async function connect() {
await client.establishSession(
'none',
'none',
uuidv4() + '@localhost',
nickname,
new Lime.GuestAuthentication(),
'chat');

console.log("connected");
setInputState(true);

return client;
} catch (e) {
console.error('Session establishment error', e);
Expand All @@ -137,7 +184,7 @@ async function connect() {
}
}

function setInputState(enabled) {
function setInputEnabled(enabled) {
if (enabled) {
msgerButton.disabled = false;
msgerInput.disabled = false;
Expand Down
Binary file added examples/ws-chat/img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 8367e03

Please sign in to comment.