changed docker file nest to avoid rebuild everything each time, and small changes in chat gateway

This commit is contained in:
simplonco
2023-01-02 18:08:50 +01:00
parent 32187fa06c
commit 1551ec6499
150 changed files with 49244 additions and 31 deletions

View File

@@ -0,0 +1,54 @@
- [socket io multi room chat](http://psitsmike.com/2011/10/node-js-and-socket-io-multiroom-chat-tutorial/)
first time :
npm install --save express socket.io cors
sudo npm install -g nodemon
next time :
npm install
anytime :
nodemon server
- [ ] don't send message to oneself
- [ ] create a room
- [ ] automatically add someone to a room
- [ ] being able to accept or refuse to be added to a room
- [ ] what to do with message not received ?
```
-> create_public_conv( room_name );
-> create_private_conv( room_name );
-> create_protected_conv( room_name );
-> create_direct_conv( room_name );
-> change_conv( room_name );
-> get_conv_history( room_name );
-> get_last_conv();
-> get_my_convs_directs( );
-> get_my_convs_rooms( );
-> get_public_convs( );
[ list ][ create ][ join ]
"directs" . [direct] (public and protected)
"rooms" . [room]
. public
. private
. protected
on connection :
get_convs_directs();
get_convs_rooms();
last_conv = get_last_conv();
if (last_conv)
get_conv_history(last_conv);
```
## todo:
- check if drop down menu works also with buttons instead of <div tabindex=0>
- add window for option when select 'room'

View File

@@ -0,0 +1,32 @@
/*
*/
let test = document.createElement('form');
test.innerHTML = `
<button onclick="chat_layout(this.innerText)" type="reset">close</button>
<br><br><button onclick="chat_layout(this.innerText)" type="reset">home</button>
<br><br><button onclick="chat_layout(this.innerText)" type="reset">room</button>
<br><br><button onclick="chat_layout(this.innerText)" type="reset">new</button>
<br><br><button onclick="chat_layout(this.innerText)" type="reset">settings</button>
<br><br><button onclick="chat_layout(this.innerText)" type="reset">room_set</button>
<br><br><button onclick="chat_layout(this.innerText)" type="reset">protected</button>
<br><br><button onclick="chat_layout(this.innerText)" type="reset">create</button>
<br><br><button onclick="chat_layout(this.innerText)" type="reset">user</button>
<br><br><label><input onchange="chat_layout_toggle(this.nextElementSibling.innerText)" type="checkbox"><span>_blocked</span></label>
<br><br><label><input onchange="chat_layout_toggle(this.nextElementSibling.innerText)" type="checkbox"><span>_admin</span></label>
<br><br><label><input onchange="chat_layout_toggle(this.nextElementSibling.innerText)" type="checkbox"><span>_muted</span></label>
<br><br><label><input onchange="chat_layout_replace('_settings', '_room_set')" type="radio" name="form_from"><span>_room_set</span></label>
<br><br><label><input onchange="chat_layout_replace('_room_set', '_settings')" type="radio" name="form_from"><span>_settings</span></label>
<br><br><button onclick="chat_layout(this.innerText)" type="reset">mute</button>
`;
document.body.prepend(test);
function chat_layout_toggle(layout_class) {
document.getElementById('chat_box').classList.toggle(layout_class);
};
function chat_layout_replace(_old, _new) {
let chat = document.getElementById('chat_box');
chat.classList.remove(_old);
chat.classList.add(_new);
};

View File

@@ -0,0 +1,444 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="./style/chat.css" type="text/css" rel="stylesheet">
<script src="./_test_layouts.js" defer></script>
</head>
<body>
<div class="close" id="chat_box">
<!--
classes:
1. close -> layout close
2. home -> layout home
3. room -> layout room
4. new -> layout new
5. settings -> layout settings
6. room_set -> layout room_set
7. protected -> layout protected
8. create -> layout create
9. mute -> layout mute
10. user -> layout user
11. _blocked -> for user layout : user is blocked
12. _muted -> for user layout : user is muted
13. _admin -> for user layout : you are admin
14. _room_set -> for user layout : comes from room_set
15. _settings -> for user layout : comes from settings
classes for layout must replace the entire previous class
but classes starting with "_" must be added to existing class
-->
<button class="chat_item chat_chat btn" id="chat_chat" onclick="chat_layout('home')" ><p>chat</p></button>
<button class="chat_item chat_close btn" id="chat_close" onclick="chat_layout('close')" title="close" ></button>
<button class="chat_item chat_new btn" id="chat_new" onclick="chat_layout('new')" title="new" ><p>new</p></button>
<button class="chat_item chat_settings btn" id="chat_settings" onclick="chat_layout('settings')" title="settings"><p>settings</p></button>
<button class="chat_item chat_room_name btn" id="chat_room_name" onclick="chat_layout('room_set')" ><p>&lt;room_name&gt;</p></button>
<p class="chat_item chat_create" id="chat_create" >create</p>
<p class="chat_item chat_user" id="chat_user" >&lt;user_name&gt;</p>
<div class="chat_item chat_back" id="chat_back"></button>
<button class="btn back_room" onclick="chat_layout('room')" title="go back room"></button>
<button class="btn back_home" onclick="chat_layout('home')" title="go back home"></button>
<button class="btn back_new" onclick="chat_layout('new')" title="go back new"></button>
<button class="btn back_user" onclick="chat_layout('user')" title="go back user"></button>
<button class="btn back_settings" onclick="chat_layout('settings')" title="go back settings"></button>
<button class="btn back_room_set" onclick="chat_layout('room_set')" title="go back room settings"></button>
</div>
<!-- --------------------------------
PANELS
- HOME
- MSG
- NEW
- SETTINGS
- ROOM SET
- PROTECTED
- CREATE
- USER
- MUTE
- WRITE
--------------------------------- -->
<!-- HOME -->
<div class="chat_item chat_panel chat_panel_home" id="chat_panel_home">
<p class="__center">list of your rooms :</p>
<div id="chat_api_room_list" class="chat_api list_btn">
<div class="chat_room_name __show_if_only_child">
<p class="__center">/ you have no chat room yet /</p>
</div>
<!-- placeholders
------------- -->
<button class="chat_room_name btn" onclick="chat_layout('room')">
<p class="__left">a room</p>
</button>
<button class="chat_room_name btn" onclick="chat_layout('room')">
<p class="__left">another room</p>
</button>
<button class="chat_room_name btn" onclick="chat_layout('room')">
<p class="__left">placeholder</p>
</button>
<!-- END placeholders -->
</div>
</div>
<!-- NEW -->
<div class="chat_item chat_panel chat_panel_new" id="chat_panel_new">
<button class="chat_create_btn btn"><p>create</p></button>
<p>join room :</p>
<div id="chat_api_publics_rooms" class="chat_api chat_public_rooms list_btn">
<div class="__show_if_only_child">
<p class="__center">/ there are no public rooms yet /</p>
</div>
<!-- placeholders
------------- -->
<button class="chat_room_name btn" onclick="chat_layout('room')">
<p class="__left">join room</p>
</button>
<button class="chat_room_name btn" onclick="chat_layout('room')">
<p class="__left">one room</p>
</button>
<button class="chat_room_name btn" onclick="chat_layout('room')">
<p class="__left">another room</p>
</button>
<button class="chat_room_name btn" onclick="chat_layout('room')">
<p class="__left">one more room</p>
</button>
<!-- END placeholders -->
</div>
</div>
<!-- SETTINGS -->
<div class="chat_item chat_panel chat_panel_settings" id="chat_panel_settings">
<p>blocked users :</p>
<div id="chat_api_blocked_users" class="chat_api chat_blocked_users list_btn">
<!-- placeholders
------------- -->
<button class="chat_user btn" onclick="chat_layout('user _settings')">
<p class="__left blocked">user 1</p>
</button>
<button class="chat_user btn" onclick="chat_layout('user _settings')">
<p class="__left blocked">user 2</p>
</button>
<button class="chat_user btn" onclick="chat_layout('user _settings')">
<p class="__left blocked">user 3</p>
</button>
<button class="chat_user btn" onclick="chat_layout('user _settings')">
<p class="__left blocked">user 4</p>
</button>
<!-- END placeholders -->
</div>
</div>
<!-- ROOM SET -->
<div class="chat_item chat_panel chat_panel_room_set" id="chat_panel_room_set">
<button class="chat_leave_btn btn"><p>leave</p></button>
<p>room users :</p>
<div id="chat_api_room_users" class="chat_api chat_room_users list_btn">
<div class="chat_public_rooms __show_if_only_child">
<p class="__center">/ there are no public rooms yet /</p>
</div>
<!-- placeholders
------------- -->
<button class="chat_room_name btn" onclick="chat_layout('user _room_set')">
<p class="__left">user 1</p>
</button>
<button class="chat_room_name btn" onclick="chat_layout('user _room_set')">
<p class="__left blocked">user 2</p>
</button>
<button class="chat_room_name btn" onclick="chat_layout('user _room_set')">
<p class="__left">user 3</p>
</button>
<button class="chat_room_name btn" onclick="chat_layout('user _room_set')">
<p class="__left">user 4</p>
</button>
<!-- END placeholders -->
</div>
</div>
<!-- PROTECTED -->
<div class="chat_item chat_panel chat_panel_protected" id="chat_panel_protected">
<p class="__center" id="chat_protected_title">this room is protected</p>
<form>
<label for="chat_pswd"><p>password :</p></label>
<input id="chat_pswd" type="password" required>
<input type="submit" value="&#x2BA1">
</form>
</div>
<!-- CREATE -->
<div class="chat_item chat_panel chat_panel_create" id="chat_panel_create">
<form>
<!-- name: -->
<label for="chat_name"><p>name :</p></label>
<input id="chat_name" required>
<!-- [ ] pubic -->
<input id="chat_public" type="radio" name="chat_create_type" checked>
<label for="chat_public" class="_radio"><p>public</p></label>
<!-- [ ] private -->
<input id="chat_private" type="radio" name="chat_create_type">
<label for="chat_private" class="_radio"><p>private</p></label>
<!-- [ ] protected -->
<input id="chat_protected" class="_check_change_next" type="radio" name="chat_create_type">
<label for="chat_protected" class="_radio"><p>protected</p></label>
<!-- [x] protected -->
<div class="__content _is_hidden">
<label for="chat_pswd"><p>choose a password :</p></label>
<input id="chat_pswd" type="password" placeholder="minimum 8 characters" minlength="8">
<p>confirm password :</p>
<input type="password">
</div>
<input type="submit" value="&#x2BA1">
</form>
</div>
<!-- USER -->
<div class="chat_item chat_panel chat_panel_user" id="chat_panel_user">
<p class="__center">user options :</p>
<div class="chat_user_btn_wrapper">
<button class="chat_profile_btn btn"><p>view profile</p></button>
<button class="chat_game_btn btn"><p>game invitation</p></button>
<button class="chat_block_btn btn">
<p id="chat_user_block">block</p>
<p id="chat_user_unblock">unblock</p>
</button>
<div id="chat_user_admin">
<button class="chat_admin_btn btn"><p>make admin</p></button>
<button class="chat_mute_btn btn" id="chat_mute_btn">
<p id="chat_user_mute">mute</p>
<p id="chat_user_unmute">unmute</p>
</button>
</div>
</div>
</div>
<!-- MUTE -->
<div class="chat_item chat_panel chat_panel_mute" id="chat_panel_mute">
<p class="__center">mute this user for a time :</p>
<form>
<!-- forever -->
<input id="chat_mute_forever" type="checkbox" class="_check_change_next"></input>
<label for="chat_mute_forever" class="_checkbox"><p>forever</p></label>
<div class="__content _is_not_gray">
<!-- minutes -->
<label for="chat_mute_minutes" class="_select">
<p>minutes :</p>
<select id="chat_mute_minutes">
<option value="01">00</option>
<option value="01">01</option>
<option value="02">02</option>
<option value="03">03</option>
<option value="04">04</option>
<option value="05">05</option>
<option value="06">06</option>
<option value="07">07</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="30">30</option>
<option value="31">31</option>
<option value="32">32</option>
<option value="33">33</option>
<option value="34">34</option>
<option value="35">35</option>
<option value="36">36</option>
<option value="37">37</option>
<option value="40">40</option>
<option value="41">41</option>
<option value="42">42</option>
<option value="43">43</option>
<option value="44">44</option>
<option value="45">45</option>
<option value="46">46</option>
<option value="47">47</option>
<option value="50">50</option>
<option value="51">51</option>
<option value="52">52</option>
<option value="53">53</option>
<option value="54">54</option>
<option value="55">55</option>
<option value="56">56</option>
<option value="57">57</option>
<option value="60">60</option>
</select>
</label>
<!-- hours -->
<label for="chat_mute_hours" class="_select">
<p>hours :</p>
<select id="chat_mute_hours">
<option value="01">00</option>
<option value="01">01</option>
<option value="02">02</option>
<option value="03">03</option>
<option value="04">04</option>
<option value="05">05</option>
<option value="06">06</option>
<option value="07">07</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="30">30</option>
<option value="31">31</option>
<option value="32">32</option>
<option value="33">33</option>
<option value="34">34</option>
<option value="35">35</option>
<option value="36">36</option>
<option value="37">37</option>
<option value="40">40</option>
<option value="41">41</option>
<option value="42">42</option>
<option value="43">43</option>
<option value="44">44</option>
<option value="45">45</option>
<option value="46">46</option>
<option value="47">47</option>
<option value="50">50</option>
<option value="51">51</option>
<option value="52">52</option>
<option value="53">53</option>
<option value="54">54</option>
<option value="55">55</option>
<option value="56">56</option>
<option value="57">57</option>
<option value="60">60</option>
</select>
</label>
<!-- days -->
<label for="chat_mute_days" class="_select">
<p>days :</p>
<select id="chat_mute_days">
<option value="00">00</option>
<option value="01">01</option>
<option value="02">02</option>
<option value="03">03</option>
<option value="04">04</option>
<option value="05">05</option>
<option value="06">06</option>
<option value="07">07</option>
<option value="10">10</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="14">14</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="17">17</option>
<option value="20">20</option>
<option value="21">21</option>
<option value="22">22</option>
<option value="23">23</option>
<option value="24">24</option>
<option value="25">25</option>
<option value="26">26</option>
<option value="27">27</option>
<option value="30">30</option>
<option value="31">31</option>
</select>
</label>
</div>
<input type="submit" value="&#x2BA1">
</form>
</div>
<!-- MSG -->
<div class="chat_item chat_panel chat_panel_msg" id="chat_panel_msg">
<div id="chat_api_msg_thread" class="chat_api">
<!-- placeholders
------------- -->
<div class="chat_msg bob">
<p class="name">bob</p>
<p class="msg">hello</p>
</div>
<div class="chat_msg me">
<p class="name">me</p>
<p class="msg">hello</p>
</div>
<!-- END placeholders -->
</div>
</div>
<!-- WRITE -->
<div class="chat_item chat_panel chat_panel_write" id="chat_panel_write">
<!--
<textarea class="text_area" id="chat_msg_write" onkeypress="send_msg_if(event)" placeholder="type here"></textarea>
-->
<div class="text_area" id="chat_msg_write" onkeypress="send_msg_if(event)" contenteditable="true" ></div>
</div>
<!-- send -->
<button class="chat_item chat_send btn" id="chat_send" onclick="send_msg()" title="send"><p>send</p></button>
<!-- --------------------------------
MODELS
<div class="chat_model" id="chat_model_myroom_name">
</div>
<div class="chat_model" id="chat_model_msg">
</div>
<div class="chat_model" id="chat_model_room_name">
</div>
<div class="chat_model" id="chat_model_blocked_user">
</div>
<div class="chat_model" id="chat_model_room_user">
</div>
--------------------------------- -->
</div>
<script>
function chat_layout(layout_class) {
document.getElementById('chat_box').className = layout_class;
};
</script>
<!-- https://socket.io/docs/v4/client-installation/ -->
<script src="https://cdn.socket.io/4.5.3/socket.io.min.js" integrity="sha384-WPFUvHkB1aHA5TDSZi6xtDgkF0wXJcIIxXhC6h8OT8EH3fC5PWro5pWJ1THjcfEi" crossorigin="anonymous"></script>
<script>
const socket = io("http://localhost:3000");
socket.on("connect", () => {
console.log("client: connection");
});
</script>
<script src="./chat_connection.js"></script>
<script src="./chat_send_msg.js"></script>
<script src="./chat_add_msg.js"></script>
<script src="./chat_create_room.js"></script>
<script src="./event_updatemsg.js"></script>
<script src="./event_updaterooms.js"></script>
</body>
</html>

View File

@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
#chat_box * {
display: flex;
flex-direction: column;
position: relative;
box-sizing: border-box;
padding: 0px;
margin: auto;
}
#chat_box .chat_item {
display: none;
width: 100%;
height: 100%;
}
.chat_item#chat_chat {
grid-area: chat;
}
#chat_box {
display: grid;
position: fixed;
bottom: 20px;
right: 20px;
gap: 5px;
padding: 5px;
width: 300px;
height: 400px;
border: 1px solid black;
}
#chat_box.close {
gap: 0px;
padding: 0px;
width: auto;
height: auto;
grid:
' chat ' auto
/ auto ;
}
#chat_box.close .chat_item#chat_chat {
display: flex;
}
</style>
</head>
<body>
<div class="close" id="chat_box">
<button class="chat_item chat_chat btn" id="chat_chat"><p>chat</p></button>
</div>
</body>
</html>

View File

@@ -0,0 +1,32 @@
const add_message = (from, message ) => {
const div_thread = document.getElementById('chat_api_msg_thread');
div_thread.appendChild(build_new_message(from, message));
}
const build_new_message = (from, message) => {
const div = document.createElement("div");
const p_name = document.createElement("p");
const p_msg = document.createElement("p");
div.classList.add("chat_msg");
div.classList.add(from);
p_name.classList.add("name");
p_msg.classList.add("msg");
p_name.appendChild(document.createTextNode(from + " :"));
p_msg.appendChild(document.createTextNode(message));
div.appendChild(p_name);
div.appendChild(p_msg);
return div;
}
/*
<div class="chat_msg bob">
<p class="name">bob</p>
<p class="msg">hello</p>
</div>
*/

View File

@@ -0,0 +1,3 @@
//const add_room = (rooms, newroom) => {
//
//};

View File

@@ -0,0 +1,5 @@
socket.on('connect', () => {
//socket.emit('adduser', prompt("what's your name ?"));
socket.emit('adduser', "glurk");
//socket.emit('joinlastroom');
});

View File

@@ -0,0 +1,5 @@
let create_room = () => {
let room_name = prompt("room name ?");
socket.emit('createroom', room_name);
};

View File

@@ -0,0 +1,32 @@
function send_msg()
{
const div_msg = document.getElementById('chat_msg_write');
let msg = "";
if (div_msg.localName === "div")
{
msg = div_msg.innerText.trim();
div_msg.innerText = "";
}
else if (div_msg.localName === "textarea")
{
msg = div_msg.value.trim();
div_msg.value = "";
}
div_msg.focus();
console.log(msg);
if (msg.length > 0) {
socket.emit('sendmsg', msg);
add_message("me", msg);
}
}
function send_msg_if(evt)
{
if (evt.shiftKey && evt.key === "Enter")
{
evt.preventDefault();
send_msg();
}
}

View File

@@ -0,0 +1,5 @@
socket.on('updatemsg', (from, data) => {
console.log("data: " + data);
add_message(from, data);
});

View File

@@ -0,0 +1,30 @@
socket.on('updaterooms', (rooms) => {
let div_rooms = document.getElementById("rooms");
console.log("rooms: ");
console.log(rooms);
// let div_room_count = div_rooms.childElementCount;
// let div_room_list = document.getElementsByClassName("room_name");
// console.log(".div_room_list: ");
// console.log(div_room_list);
// for(let room of div_room_list) {
// console.log(room);
// console.log(room.innerHTML);
// }
div_rooms.innerHTML = "";
for (let room of rooms) {
//console.log(room.name);
const label = document.createElement("label");
const p = document.createElement("p");
const p_content = document.createTextNode(room.name);
label.setAttribute('for', "input_outside");
p.className = "room_name";
p.appendChild(p_content);
label.appendChild(p);
div_rooms.appendChild(label);
}
});

View File

@@ -0,0 +1,82 @@
/*
*/
@import 'chat__global.css';
@import 'layout_close.css';
@import 'layout_home.css';
@import 'layout_room.css';
@import 'layout_new.css';
@import 'layout_settings.css';
@import 'layout_room_set.css';
@import 'layout_protected.css';
@import 'layout_create.css';
@import 'layout_user.css';
@import 'layout_mute.css';
@import 'chat_panels.css';
@import 'chat_buttons.css';
@import 'chat_back.css';
@import 'chat_close.css';
@import 'chat_write.css';
@import 'chat_msg.css';
@import 'chat_blocked.css';
@import 'chat_form.css';
/*
GRID
*/
#chat_box * {
display: flex;
flex-direction: column;
position: relative;
box-sizing: border-box;
padding: 0px;
margin: auto;
}
#chat_box .chat_item {
display: none;
/*
border: 1px solid black;
*/
width: 100%;
height: 100%;
}
.chat_item#chat_chat { grid-area: chat;}
.chat_item#chat_close { grid-area: close;}
.chat_item#chat_new { grid-area: new;}
.chat_item#chat_settings { grid-area: settings;}
.chat_item#chat_room_name { grid-area: room_name;}
.chat_item#chat_send { grid-area: send;}
.chat_item#chat_create { grid-area: create;}
.chat_item#chat_user { grid-area: user;}
.chat_item#chat_back { grid-area: back;}
.chat_item#chat_panel_home { grid-area: panel_home;}
.chat_item#chat_panel_new { grid-area: panel_new;}
.chat_item#chat_panel_msg { grid-area: panel_msg;}
.chat_item#chat_panel_write { grid-area: panel_write;}
.chat_item#chat_panel_settings { grid-area: panel_settings;}
.chat_item#chat_panel_room_set { grid-area: panel_room_set;}
.chat_item#chat_panel_protected { grid-area: panel_protected;}
.chat_item#chat_panel_create { grid-area: panel_create;}
.chat_item#chat_panel_user { grid-area: panel_user;}
.chat_item#chat_panel_mute { grid-area: panel_mute;}
#chat_box {
display: grid;
position: fixed;
bottom: 20px;
right: 20px;
gap: 5px;
padding: 5px;
width: 300px;
height: 400px;
border: 1px solid black;
}

View File

@@ -0,0 +1,67 @@
/* Hide scrollbar
*/
#chat_box * {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
#chat_box *::-webkit-scrollbar {
display: none; /* Chrome, Safari and Opera */
}
/* p in chat_box
*/
#chat_box p {
padding: 10px;
font-size: 15px;
font-family: Cantarell;
}
/* show child only if it's alone
*/
#chat_box .__show_if_only_child {
display: none;
}
#chat_box .__show_if_only_child:only-child {
display: flex;
color: rgb(100, 100, 100);
}
/* separation line under controls
*/
#chat_box .chat_item.chat_panel {
border-top: 1px solid black;
}
/* text align
*/
#chat_box p.__center {
text-align: center;
}
#chat_box p.__left {
text-align: left;
}
#chat_box p.__right {
text-align: right;
}
/* default align items
*/
#chat_box .chat_item > * {
margin: 0px;
}
/* display content
*/
#chat_box .__content{
display: content;
}

View File

@@ -0,0 +1,39 @@
/*
https://www.fileformat.info/info/unicode/category/So/list.htm
U+1F512 LOCK 🔒
U+1F513 OPEN LOCK 🔓
*/
#chat_box .blocked {
padding-left: 30px;
}
#chat_box .blocked::before {
content: "";
position: absolute;
top: calc(50% - 2px);
left: 10px;
cursor: pointer;
width: 13px;
height: 10px;
border-radius: 2px;
/*
*/
background-color: rgb(110, 110, 110);
}
#chat_box .blocked::after {
content: "";
position: absolute;
top: calc(50% - 9px);
left: 12px;
cursor: pointer;
width: 9px;
height: 13px;
border-radius: 5px;
box-sizing: border-box;
/*
background-color: red;
*/
border: 3px solid rgb(110, 110, 110);
}

View File

@@ -0,0 +1,55 @@
#chat_box button {
display: flex;
width: auto;
cursor: pointer;
outline: none;
border: none;
background-color: rgb(220, 220, 220);
}
#chat_box button p {
width: 100%;
text-align: center;
}
#chat_box button.chat_item:hover,
#chat_box .chat_item button:hover {
background-color: rgb(200, 200, 200);
}
#chat_box button.chat_item:active,
#chat_box .chat_item button:active {
background-color: rgb(190, 190, 190);
}
/* BTN LIST
add or remove '.btn' to toggle the hover effect
*/
#chat_box .list_btn button {
margin: 0px;
background-color: transparent;
}
#chat_box .list_btn {
background-color: rgb(240, 240, 240);
}
/* BACK
*/
#chat_box .chat_item.chat_back button {
width: 30px;
height: 100%;
background-color: transparent;
display: none;
}
#chat_box .chat_item.chat_back button::before {
content: "";
position: absolute;
top: calc(50% - 6px - 1px);
left: 6px;
width: 14px;
height: 14px;
border-left: 1px solid black;
border-bottom: 1px solid black;
transform: rotate(45deg);
}

View File

@@ -0,0 +1,20 @@
#chat_box .chat_item#chat_close {
width: 30px;
}
/* add or remove '.chat_item' to toggle the hover effect */
#chat_box button.chat_item.chat_close {
width: 100%;
height: 100%;
padding: 0px;
background-color: transparent;
}
#chat_close::before {
content: "";
position: absolute;
top: calc(50% - 1px);
left: 5px;
width: 20px;
height: 2px;
background-color: black;
}

View File

@@ -0,0 +1,120 @@
/* default element take all space on each line
*/
#chat_box .chat_item form {
margin: 0px auto;
}
#chat_box .chat_item form * {
margin: 0px;
}
/* radio elements style check
*/
#chat_box .chat_item form input[type=radio] {
display: none;
}
#chat_box .chat_item form label._radio {
margin: 0px 0px 0px auto;
padding-right: 10px;
cursor: pointer;
}
#chat_box .chat_item form label._radio::after {
content: "";
position: absolute;
top: calc(50% - 6px);
right: 0px;
width: 12px;
height: 12px;
border-radius: 6px;
border: 2px solid rgb(150, 150, 150);
box-sizing: border-box;
cursor: pointer;
}
#chat_box .chat_item form input[type=radio]:checked
+ label._radio::after {
background-color: rgb(200, 200, 200);
}
/* change next element on check
*/
#chat_box form ._check_change_next:checked ~ ._is_hidden {
display: flex;
}
#chat_box form ._check_change_next:checked ~ ._is_not_gray {
pointer-events: none;
color: rgb(100, 100, 100);
}
#chat_box form ._is_hidden {
display: none;
}
/* submit button
https://www.fileformat.info/info/unicode/category/So/list.htm
U+21AA RIGHTWARDS ARROW WITH HOOK ↪
U+21B3 DOWNWARDS ARROW WITH TIP RIGHTWARDS ↳
U+2BA1 DOWNWARDS TRIANGLE-HEADED ARROW WITH LONG TIP RIGHTWARDS ⮡
U+2BB1 RIBBON ARROW DOWN RIGHT ⮱
U+2BA9 BLACK CURVED DOWNWARDS AND RIGHTWARDS ARROW ⮩
*/
#chat_box .chat_item form input[type=submit] {
padding: 0px 10px;
border: none;
margin: 10px 0px 0px auto;
cursor: pointer;
background-color: rgb(220, 220, 220);
}
#chat_box .chat_item form input[type=submit]:hover {
background-color: rgb(200, 200, 200);
}
/* select
*/
#chat_box .chat_item form label._select {
flex-direction: row;
margin-left: auto;
}
#chat_box .chat_item form select {
margin: auto 0px;
background-color: rgb(220, 220, 220);
border: none;
padding: 5px;
cursor: pointer;
}
#chat_box .chat_item form select:hover {
background-color: rgb(200, 200, 200);
}
/* checkbox
<input id="chat_mute_forever" type="checkbox" class="_checkbox"></input>
<label for="chat_mute_forever">forever</label>
*/
#chat_box .chat_item form input[type=checkbox] {
display: none;
}
#chat_box .chat_item form label._checkbox {
margin: 0px 0px 0px auto;
padding-right: 10px;
cursor: pointer;
}
#chat_box .chat_item form label._checkbox::after {
content: "";
position: absolute;
top: calc(50% - 6px);
right: 0px;
width: 12px;
height: 12px;
border: 2px solid rgb(150, 150, 150);
box-sizing: border-box;
cursor: pointer;
}
#chat_box .chat_item form input[type=checkbox]:checked
+ label._checkbox::after {
background-color: rgb(200, 200, 200);
}

View File

@@ -0,0 +1,75 @@
#chat_box #chat_panel_msg {
flex-direction: column-reverse;
overflow: scroll;
border: 1px solid black;
}
#chat_box #chat_panel_msg #chat_api_msg_thread {
flex-direction: column;
width: 100%;
padding: 0px 5px;
margin-bottom: 0px;
}
#chat_box #chat_panel_msg #chat_api_msg_thread .chat_msg {
white-space: pre-wrap;
margin: 5px auto;
padding: 5px;
border-radius: 5px;
}
/* * * * * * * * * * * * * *
ALL MSG
*/
#chat_box #chat_panel_msg #chat_api_msg_thread .chat_msg {
margin-left: 0px;
background-color: rgb(210, 210, 210);
max-width: 80%;
}
#chat_box #chat_panel_msg #chat_api_msg_thread .chat_msg p {
padding: 0px;
}
#chat_box #chat_panel_msg #chat_api_msg_thread .chat_msg p.name {
margin: 0px;
margin-bottom: 5px;
font-size: 12px;
color: rgb(100, 100, 100);
}
#chat_box #chat_panel_msg #chat_api_msg_thread .chat_msg p.msg {
/*
margin: 5px 0px;
line-height: 8px;
*/
}
/* * * * * * * * * * * * * *
MSG PERSO
*/
#chat_box #chat_panel_msg #chat_api_msg_thread .chat_msg.me {
margin-right: 0px;
margin-left: auto;
background-color: rgb(210, 110, 10);
}
#chat_box #chat_panel_msg #chat_api_msg_thread .chat_msg.me p.name {
display: none;
}
/* * * * * * * * * * * * * *
MSG SERVER
*/
#chat_box #chat_panel_msg #chat_api_msg_thread .chat_msg.SERVER {
margin-left: auto;
background-color: transparent;
}
#chat_box #chat_panel_msg #chat_api_msg_thread .chat_msg.SERVER p.name {
display: none;
}
#chat_box #chat_panel_msg #chat_api_msg_thread .chat_msg.SERVER p.msg {
margin: 0px auto;
font-size: 12px;
color: rgb(100, 100, 100);
}

View File

@@ -0,0 +1,3 @@
#chat_box .chat_panel {
overflow-y: scroll;
}

View File

@@ -0,0 +1,36 @@
#chat_box .chat_item#chat_panel_write {
border: none;
overflow: visible;
}
#chat_box .chat_item#chat_panel_write .text_area {
display: block;
position: absolute;
bottom: 0px;
left: 0px;
width: 100%;
overflow-x: hidden;
overflow-y: scroll;
background-color: white;
border: 1px solid black;
}
#chat_box .chat_item#chat_panel_write .text_area * {
display: block ruby;
}
/* if .text_area is a contenteditable div
*/
#chat_box .chat_item#chat_panel_write .text_area {
height: auto;
min-height: 100%;
max-height: 300px;
}
/* if .text_area is a textarea
*/
#chat_box .chat_item#chat_panel_write textarea.text_area {
resize: none;
height: 100px;
}
#chat_box .chat_item#chat_panel_write textarea.text_area:placeholder-shown {
height: 100%;
}

View File

@@ -0,0 +1,58 @@
#chat_box.close {
gap: 0px;
padding: 0px;
width: auto;
height: auto;
grid:
' chat ' auto
/ auto ;
}
#chat_box.close .chat_item#chat_chat {
display: flex;
}
/*
* COLLAPSE
.chat._item:not(.open_close) {
display: none;
}
#chat_input:checked ~
#chat_box {
gap: 5px;
padding: 5px;
width: 300px;
height: 400px;
}
#chat_input:checked ~
#chat_box .chat._item {
display: flex;
}
#chat_input:checked ~
#chat_box .chat._item.open_close p {
display: none;
}
#chat_input:checked ~
#chat_box .chat._item.open_close {
width: 30px;
height: 20px;
padding: 0px;
justify-self: end;
background-color: transparent;
border: none;
}
#chat_input:checked ~
#chat_box .chat._item.open_close::before {
content: "";
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
height: 4px;
width: 15px;
background-color: black;
}
*/

View File

@@ -0,0 +1,28 @@
#chat_box.create {
grid:
' back create close ' auto
' panel_create panel_create panel_create ' 1fr
/ auto 1fr auto ;
}
#chat_box.create .chat_item#chat_back,
#chat_box.create .chat_item#chat_create,
#chat_box.create .chat_item#chat_close,
#chat_box.create .chat_item#chat_panel_create {
display: flex;
}
/* back btn
*/
#chat_box.create .chat_item.chat_back button.back_new {
display: flex;
}
/* title "create" appearance
*/
#chat_box.create .chat_item.chat_create {
text-align: center;
}

View File

@@ -0,0 +1,54 @@
#chat_box.home {
grid:
' settings new close ' auto
' panel_home panel_home panel_home ' 1fr
/ auto 1fr auto ;
}
#chat_box.home .chat_item#chat_settings,
#chat_box.home .chat_item#chat_new,
#chat_box.home .chat_item#chat_close,
#chat_box.home .chat_item#chat_panel_home {
display: flex;
}
/* button "new" appearance
*/
/* add or remove '.chat_item' to toggle the hover effect */
#chat_box.home button.chat_new {
width: auto;
background-color: transparent;
}
/* button "settings" as 3 dots
*/
#chat_box.home .chat_item#chat_settings p {
display: none;
}
#chat_box.home button.chat_item#chat_settings {
width: 30px;
height: 100%;
padding: 0px;
}
/* add or remove '.chat_item' to toggle the hover effect */
#chat_box.home button.chat_item#chat_settings {
background-color: transparent;
}
#chat_box.home .chat_item#chat_settings::after {
content: '\2807';
font-size: 20px;
position: absolute;
top: 50%;
left: 0px;
width: 100%;
height: auto;
text-align: center;
transform: translateY(-50%);
cursor: pointer;
/*
background-color: black;
*/
}

View File

@@ -0,0 +1,30 @@
#chat_box.mute {
grid:
' back user close ' auto
' panel_mute panel_mute panel_mute ' 1fr
/ auto 1fr auto ;
}
#chat_box.mute .chat_item#chat_back,
#chat_box.mute .chat_item#chat_user,
#chat_box.mute .chat_item#chat_close,
#chat_box.mute .chat_item#chat_panel_mute {
display: flex;
}
/* back btn
*/
#chat_box.mute .chat_item.chat_back button.back_user {
display: flex;
}
/* title "mute" appearance
*/
#chat_box.mute .chat_item.chat_user {
text-align: center;
}

View File

@@ -0,0 +1,40 @@
#chat_box.new {
grid:
' back new close ' auto
' panel_new panel_new panel_new ' 1fr
/ auto 1fr auto ;
}
#chat_box.new .chat_item#chat_back,
#chat_box.new .chat_item#chat_new,
#chat_box.new .chat_item#chat_close,
#chat_box.new .chat_item#chat_panel_new {
display: flex;
}
/* back btn
*/
#chat_box.new .chat_item.chat_back button.back_home {
display: flex;
}
/* button "new" appearance
*/
/* add or remove '.chat_item' to toggle the hover effect */
#chat_box.new button.chat_item.chat_new {
width: auto;
background-color: transparent;
pointer-events: none;
}
/* button "create" appearance
*/
#chat_box.new .chat_item button.chat_create_btn {
margin: 10px 0px;
}

View File

@@ -0,0 +1,36 @@
#chat_box.protected {
grid:
' back room_name close ' auto
' panel_protected panel_protected panel_protected ' 1fr
/ auto 1fr auto ;
}
#chat_box.protected .chat_item#chat_back,
#chat_box.protected .chat_item#chat_room_name,
#chat_box.protected .chat_item#chat_close,
#chat_box.protected .chat_item#chat_panel_protected {
display: flex;
}
/* back btn
*/
#chat_box.protected .chat_item.chat_back button.back_new {
display: flex;
}
/* button "<room_name>" appearance
add or remove '.chat_item' to toggle the hover effect
*/
#chat_box.protected button.chat_item.chat_room_name {
width: auto;
background-color: transparent;
pointer-events: none;
}
#chat_box #chat_protected_title {
margin-top: 30px;
}

View File

@@ -0,0 +1,34 @@
#chat_box.room {
grid:
' back room_name room_name close ' auto
' panel_msg panel_msg panel_msg panel_msg ' 1fr
' panel_write panel_write send send ' auto
/ auto 1fr auto auto ;
}
#chat_box.room .chat_item#chat_back,
#chat_box.room .chat_item#chat_room_name,
#chat_box.room .chat_item#chat_close,
#chat_box.room .chat_item#chat_panel_msg,
#chat_box.room .chat_item#chat_send,
#chat_box.room .chat_item#chat_panel_write {
display: flex;
}
/* back btn
*/
#chat_box.room .chat_item.chat_back button.back_home {
display: flex;
}
/* button "<room_name>" appearance
*/
/* add or remove '.chat_item' to toggle the hover effect */
#chat_box.room button.chat_room_name {
width: auto;
background-color: transparent;
}

View File

@@ -0,0 +1,38 @@
#chat_box.room_set {
grid:
' back room_name close ' auto
' panel_room_set panel_room_set panel_room_set ' 1fr
/ auto 1fr auto ;
}
#chat_box.room_set .chat_item#chat_back,
#chat_box.room_set .chat_item#chat_room_name,
#chat_box.room_set .chat_item#chat_close,
#chat_box.room_set .chat_item#chat_panel_room_set {
display: flex;
}
/* back btn
*/
#chat_box.room_set .chat_item.chat_back button.back_room {
display: flex;
}
/* button "<room_name>" appearance
*/
/* add or remove '.chat_item' to toggle the hover effect */
#chat_box.room_set button.chat_item.chat_room_name {
width: auto;
background-color: transparent;
pointer-events: none;
}
/* button "leave" appearance
*/
#chat_box.room_set .chat_item button.chat_leave_btn {
margin: 10px 0px;
}

View File

@@ -0,0 +1,32 @@
#chat_box.settings {
grid:
' back settings close ' auto
' panel_settings panel_settings panel_settings ' 1fr
/ auto 1fr auto ;
}
#chat_box.settings .chat_item#chat_back,
#chat_box.settings .chat_item#chat_settings,
#chat_box.settings .chat_item#chat_close,
#chat_box.settings .chat_item#chat_panel_settings {
display: flex;
}
/* back btn
*/
#chat_box.settings .chat_item.chat_back button.back_home {
display: flex;
}
/* button "settings" appearance
*/
/* add or remove '.chat_item' to toggle the hover effect */
#chat_box.settings button.chat_item.chat_settings {
width: auto;
background-color: transparent;
pointer-events: none;
}

View File

@@ -0,0 +1,80 @@
#chat_box.user {
grid:
' back user close ' auto
' room_name room_name room_name ' auto
' panel_user panel_user panel_user ' 1fr
/ auto 1fr auto ;
}
#chat_box.user .chat_item#chat_back,
#chat_box.user .chat_item#chat_user,
#chat_box.user .chat_item#chat_close,
#chat_box.user .chat_item#chat_panel_user {
display: flex;
}
/* title "user" appearance
*/
#chat_box.user .chat_item.chat_user {
text-align: center;
}
/* for line height
*/
#chat_box.user .chat_item.chat_panel_user {
margin-top: -5px;
}
/* room_name appearance
*/
#chat_box.user button.chat_item#chat_room_name {
background-color: transparent;
border-top: 1px solid black;
}
/* back btn
*/
#chat_box.user .chat_item.chat_back button.back_home {display: flex;}
/* from settings */
#chat_box._settings .chat_item.chat_back button.btn {display: none;}
#chat_box._settings .chat_item.chat_back button.back_settings {display: flex;}
/* from room settings */
#chat_box._room_set .chat_item.chat_back button.btn {display: none;}
#chat_box._room_set .chat_item.chat_back button.back_room_set {display: flex;}
/* buttons appearance
*/
#chat_box.user .chat_item.chat_panel_user .chat_user_btn_wrapper {
margin: 0px auto;
}
#chat_box.user .chat_item.chat_panel_user button {
margin: 10px;
}
#chat_box.user #chat_user_admin {
margin: 0px;
}
/* toggle buttons according to chat_box class
*/
/* block/unblock */
#chat_box.user #chat_user_unblock {display: none;}
#chat_box.user._blocked #chat_user_block {display: none;}
#chat_box.user._blocked #chat_user_unblock {display: flex;}
/* admin if from room */
#chat_box.user #chat_user_admin {display: none;}
#chat_box.user._room_set._admin #chat_user_admin {display: flex;}
/* room_name if from room */
#chat_box.user #chat_room_name {display: none;}
#chat_box.user._room_set #chat_room_name {display: flex;}
/* mute/unmute */
#chat_box.user #chat_user_unmute {display: none;}
#chat_box.user._muted #chat_user_mute {display: none;}
#chat_box.user._muted #chat_user_unmute {display: flex;}

View File

@@ -0,0 +1,21 @@
const add_user = (socket, username, usernames, rooms) => {
//console.log(`adduser: ${username}, ${usernames[username]}`);
// store the username in the socket session for this client
socket.username = username;
// store the room name in the socket session for this client
socket.room = 'room1';
// add the client's username to the global list
usernames[username] = username;
// send client to room 1
socket.join('room1');
// echo to client they've connected
socket.emit('updatemsg', 'SERVER', 'you have connected to room1');
// echo to room 1 that a person has connected to their room
socket.broadcast.to('room1').emit('updatemsg', 'SERVER', username + ' has connected to this room');
socket.emit('updaterooms', rooms);
};
module.exports = add_user;

View File

@@ -0,0 +1,9 @@
const create_room = (room_name) => {
//console.log('createroom');
let last_room = rooms[rooms.length - 1];
rooms.push({ name: room_name, id: last_room.id + 1 });
socket.emit('updaterooms', rooms);
};
module.exports = create_room;

View File

@@ -0,0 +1,8 @@
const send_msg = (socket, msg) => {
//console.log('message from: ' + socket.username);
//console.log('message received: ' + msg);
socket.to(socket.room).emit('updatemsg', socket.username, msg);
};
module.exports = send_msg;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
{
"dependencies": {
"cors": "^2.8.5",
"express": "^4.18.2",
"socket.io": "^4.5.4"
}
}

View File

@@ -0,0 +1,74 @@
const express = require('express');
const app = express();
const http = require('http');
const server = http.createServer(app);
const { Server } = require("socket.io");
// https://socket.io/docs/v4/handling-cors/
const io = new Server(server, {
cors: {
// change this for the real front origin
origin: "*"
}
});
const send_msg = require('./event_sendmsg');
const add_user = require('./event_adduser');
const create_room = require('./event_createroom');
let usernames = {};
let rooms = [
{ name: 'room1', id: 1 },
{ name: 'room2', id: 2 },
{ name: 'room3', id: 3 }
];
let last_room = 0;
io.on('connection', (socket) => {
socket.on('adduser', (username) => {
add_user(socket, username, usernames, rooms);
});
socket.on('sendmsg', (msg) => {
send_msg(socket, msg);
});
socket.on('createroom', (room_name) => {
create_room(room_name);
});
socket.on('joinlastroom', () => {
if (socket.room !== null)
socket.emit('updaterooms', socket.room);
});
socket.on('switchroom', function(newroom){
// leave the current room (stored in session)
socket.leave(socket.room);
// join new room, received as function parameter
socket.join(newroom);
socket.emit('updatechat', 'SERVER', 'you have connected to '+ newroom);
// sent message to OLD room
socket.broadcast.to(socket.room).emit('updatechat', 'SERVER', socket.username+' has left this room');
// update socket session room title
socket.room = newroom;
socket.broadcast.to(newroom).emit('updatechat', 'SERVER', socket.username+' has joined this room');
// socket.emit('updaterooms', rooms, newroom);
});
socket.on('disconnect', () => {
// remove the username from global usernames list
delete usernames[socket.username];
// update list of users in chat, client-side
io.sockets.emit('updateusers', usernames);
// echo globally that this client has left
socket.broadcast.emit('updatechat', 'SERVER', socket.username + ' has disconnected');
socket.leave(socket.room);
});
});
server.listen(3000, function () {
console.log('server running on 3000');
})