Compare commits

..

No commits in common. "07117763bfb1944df09c7ddb719c39cd589c3b57" and "49791b52762e3a9a864842a872396b5bf34fb180" have entirely different histories.

11 changed files with 94 additions and 151 deletions

41
api.js
View File

@ -21,42 +21,17 @@ const wss = new ws.Server({
}); });
//WS handler //WS handler
let user = [];
wss.on('connection', (ws, req) => { wss.on('connection', (ws, req) => {
let thisuser = ""
console.log(`${req.socket.remoteAddress} connected`) console.log(`${req.socket.remoteAddress} connected`)
ws.on('message', msgJSON => { ws.on('message', msgJSON => {
let msg = JSON.parse(msgJSON) let msg = JSON.parse(msgJSON)
console.log(`${req.socket.remoteAddress} (${thisuser}) => ${msgJSON}`) console.log(`${req.socket.remoteAddress} => ${msgJSON}`)
if (msg.type === 'message') if (msg.type === 'message') wss.clients.forEach(client => client.send(msgJSON))
if (thisuser === ""){
ws.send(JSON.stringify({type: "error", content: "please login before writing"}))
ws.send('{"type":"route","path":"/login"}')
}else if (msg.content.text === "")
ws.send(JSON.stringify({type: "error", content: "your message was empty"}))
else{
msg.content.user = thisuser
msg.content.text = msg.content.text.replace(/</g, "&lt").replace(/>/g, "&gt").replace(/\n/g, "<br>")
wss.clients.forEach(client => client.send(JSON.stringify(msg)))
}
else if (msg.type === 'login' && msg.content.user !== ""){
if (msg.content.user.length >= 20) ws.send(JSON.stringify({type: "error", content: "username is too long"}))
else if (msg.content.user === "you" || user.indexOf(msg.content.user) !== -1)
ws.send(JSON.stringify({type: "error", content: "username already exist"}))
else{
thisuser = msg.content.user
user.push(msg.content.user)
ws.send('{"type":"route","path":"/chat"}')
ws.send(JSON.stringify({type: "info", username: thisuser}))
wss.clients.forEach(client =>
client.send(JSON.stringify({type: "room", name: "open chat", user: user})))
}
}
}) })
ws.on('close', () => { let msg = {
user.splice(user.indexOf(thisuser), 1); type: "info",
console.log(`${req.socket.remoteAddress} (${thisuser}) closed`) time: Date.now(),
}) content: "connected"
}
ws.send(JSON.stringify({type: "info", time: Date.now(), content: "connected"})) ws.send(JSON.stringify(msg))
}) })

View File

@ -3,10 +3,6 @@
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<!-- PWA support -->
<link rel="manifest" href="./manifest.json"/>
<meta name="theme-color" content="#2F3BA2"/>
<meta name="description" content="open chat"/>
<meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0'/> <meta name='viewport' content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0'/>
<link rel="icon" href="<%= BASE_URL %>favicon.ico"/> <link rel="icon" href="<%= BASE_URL %>favicon.ico"/>
<title><%= htmlWebpackPlugin.options.title %></title> <title><%= htmlWebpackPlugin.options.title %></title>

View File

@ -1,9 +0,0 @@
{
"name": "open chat",
"short_name": "open chat",
"start_url": "/",
"display": "standalone",
"background_color": "#14181b",
"theme_color": "#00BCD4",
"orientation": "portrait-primary"
}

BIN
public/sym/placeholder.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -1,23 +1,28 @@
<template> <template>
<div id="chatInformation"> <div class="chatInformation">
<h1>open chat</h1> <h1>open chat</h1>
<icon class="closeBtn" onclick="this.parentNode.style.display = 'none'" ic="./sym/ic_close_white_24px.svg" /> <icon class="closeBtn" onclick="this.parentNode.style.display = 'none'" ic="./sym/ic_close_white_24px.svg" />
<div id="box"> <div id="box">
<div class="informationBox"> <div class="informationBox">
<div class="picBoxBig"><div class="placeholderBig"><p>{{chatroom.name.substr(0,2)}}</p></div></div> <div class="picBoxBig"><div class="placeholderBig"><p>O P</p></div></div>
<div class="roomInformation"> <div class="roomInformation">
<div class="roomName">{{chatroom.name}}</div> <div class="roomName">Open Chat room</div>
<div class="users">{{chatroom.user.length}} members</div> <div class="users">2 members</div>
</div> </div>
</div> </div>
<h2 v-if="chatroom.user.length !== 0">members</h2> <div id="textMembers">Members</div>
<div v-for="user in chatroom.user" :key="user"> <div class="contentBox">
<div class="contentBox"> <div class="picBox"><div class="picPlaceholder"><p>O P</p></div></div>
<div class="picBox"><div class="picPlaceholder"><p>{{user.substr(0,2)}}</p></div></div> <div class="information">
<div class="information"> <div class="userName">TechCrafter07</div>
<div class="userName">{{user}}</div> <div class="status">Online</div>
<div class="status">online</div> </div>
</div> </div>
<div class="contentBox">
<div class="picBox"><div class="picPlaceholder"><p>O P</p></div></div>
<div class="information">
<div class="userName">Alban</div>
<div class="status">Online</div>
</div> </div>
</div> </div>
</div> </div>
@ -25,38 +30,30 @@
</template> </template>
<script> <script>
import icon from './icon.vue'; import icon from './icon.vue';
import main from '@/main.js'
export default { export default {
name: "chatInformation", name: "chatInformation",
components:{ components:{
icon icon
},
data(){
return {
chatroom: main.data().chatroom
}
} }
} }
</script> </script>
<style scoped> <style scoped>
#chatInformation{ .chatInformation{
position: absolute; position: absolute;
left: 50%; left: 50%;
transform: translate(-50%, 0); transform: translate(-50%, 0);
top: 5rem; top: 5rem;
width: calc(100% - 8rem); width: calc(100% - 8rem);
max-width: 30rem;
height: calc(100% - 10rem); height: calc(100% - 10rem);
background-color: #1d1d1d; background-color: #1d1d1d;
box-shadow: 6px 6px 20px #111; box-shadow: 6px 6px 20px #111;
border-radius: 1rem; border-radius: 1rem;
text-align: center; text-align: center;
display: none;
} }
@media (max-width: 30rem) { @media (max-width: 30rem) {
#chatInformation{ .chatInformation{
transform: unset; transform: unset;
top: 0; top: 0;
left: 0; left: 0;
@ -74,14 +71,16 @@ export default {
#box{ #box{
position: relative; position: relative;
width: calc(100% - 2rem); width: calc(100% - 2rem);
background-color: #2d2d2d;
padding: 0.001rem 1rem 1rem; padding: 0.001rem 1rem 1rem;
overflow-y: auto; overflow: auto;
max-height: calc(100% - 8rem); max-height: calc(100% - 8rem);
} }
.informationBox{ .informationBox{
margin-top: 0.2rem; margin-top: 0.2rem;
height: 5rem; height: 5rem;
padding: 0.2rem; padding: 0.2rem;
border-bottom: 2px solid #9c9c9c;
} }
.picBoxBig{ .picBoxBig{
text-align: center; text-align: center;
@ -108,9 +107,17 @@ export default {
font-size: 1.2rem; font-size: 1.2rem;
color: #9c9c9c; color: #9c9c9c;
} }
#textMembers{
font-size: 1.5rem;
text-align: left;
margin-left: 0.2rem;
margin-top: 0.3rem;
margin-bottom: 0.2rem;
}
.contentBox{ .contentBox{
margin-top: 0.2rem; margin-top: 0.2rem;
height: 3.2rem; height: 3.2rem;
border-bottom: 2px solid #9c9c9c ;
padding: 0.2rem; padding: 0.2rem;
max-height: 48px; max-height: 48px;
} }

View File

@ -32,6 +32,5 @@ export default {
background-color: #42b983; background-color: #42b983;
border-radius: 1rem 1rem 1rem 0; border-radius: 1rem 1rem 1rem 0;
text-align: left; text-align: left;
word-break: break-word;
} }
</style> </style>

View File

@ -9,8 +9,8 @@
</template> </template>
<script> <script>
import icon from '@/components/icon.vue'; import icon from './icon.vue';
import main from '@/main.js'; import main from '../main.js';
export default { export default {
name: "newMessage", name: "newMessage",
@ -23,10 +23,7 @@ export default {
this.msg.time = Date.now() this.msg.time = Date.now()
main.methods.sendWebSocket(this.msg) main.methods.sendWebSocket(this.msg)
this.msg.content.text = "" this.msg.content.text = ""
document.getElementById("messagesContainer").style.height = "calc(100% - 7rem)" this.resizeMessageBanner()
document.getElementById("newMessageInput").style.height = "1.25rem"
let msgContainer = document.getElementById("messagesContainer")
msgContainer.scrollTo(0, msgContainer.scrollHeight)
} }
}, },
resizeMessageBanner(){ resizeMessageBanner(){
@ -36,6 +33,7 @@ export default {
let msgContainer = document.getElementById("messagesContainer") let msgContainer = document.getElementById("messagesContainer")
msgContainer.style.height msgContainer.style.height
= `calc(100% - ${id.parentElement.clientHeight}px - 3rem)` = `calc(100% - ${id.parentElement.clientHeight}px - 3rem)`
//msgContainer.scrollTo(0, msgContainer.scrollHeight)
} }
}, },
data(){ data(){
@ -44,11 +42,9 @@ export default {
type: "message", type: "message",
time: Date.now(), time: Date.now(),
content: { content: {
user: "you",
text: "" text: ""
} }
}, }
chatroom: main.data().chatroom
} }
} }
} }
@ -71,7 +67,7 @@ export default {
margin-bottom: 1rem; margin-bottom: 1rem;
left: 2rem; left: 2rem;
min-height: 1.25rem; min-height: 1.25rem;
max-height: 10rem; max-height: 14rem;
width: calc(100% - 7rem); width: calc(100% - 7rem);
height: 1.25rem; height: 1.25rem;
background-color: #fff0; background-color: #fff0;

View File

@ -1,13 +1,11 @@
<template> <template>
<div class="topBanner"> <div class="topBanner">
<div> <div>
<router-link to="login"> <icon class="smallIcon" id="icon-arrow" ic="./sym/arrow_back-24px.svg" />
<icon class="smallIcon" id="icon-arrow" ic="./sym/arrow_back-24px.svg" />
</router-link>
<icon class="smallIcon" id="picTop" ic="./sym/supervisor_account-24px.svg" /> <icon class="smallIcon" id="picTop" ic="./sym/supervisor_account-24px.svg" />
<div id="container"> <div id="container">
<div id="chatName">{{chatroom.name}}</div> <div id="chatName">{{roomInfo.name}}</div>
<div id="users">{{chatroom.user.length}} members</div> <div id="users">{{roomInfo.user.length}} members</div>
</div> </div>
<icon v-on:click.native="showChatInfo()" class="smallIcon" id="icon-menu" ic="./sym/menu-24px.svg" /> <icon v-on:click.native="showChatInfo()" class="smallIcon" id="icon-menu" ic="./sym/menu-24px.svg" />
</div> </div>
@ -15,7 +13,6 @@
</template> </template>
<script> <script>
import icon from '@/components/icon.vue'; import icon from '@/components/icon.vue';
import main from '@/main.js';
export default { export default {
name: "topBanner", name: "topBanner",
@ -29,7 +26,10 @@ export default {
}, },
data(){ data(){
return { return {
chatroom: main.data().chatroom roomInfo: {
name: "open chat",
user: []
}
} }
} }
} }
@ -40,7 +40,7 @@ export default {
width: 100%; width: 100%;
height: 3rem; height: 3rem;
background-color: #1d1d1d; background-color: #1d1d1d;
box-shadow: 0 0px 5px #111; box-shadow: 0 3px 10px #111;
} }
.smallIcon{ .smallIcon{
top: 0.25rem; top: 0.25rem;

View File

@ -27,22 +27,17 @@ const router = new VueRouter({
] ]
}) })
let chatroom = { new Vue({
name: "open chat", el: '#app',
user: [], router,
username: "you", template: '<App/>',
messages: [] components: {App}
}; }).$mount('#app')
export default { export default {
mounted() { mounted() {
sendMessage() sendMessage()
}, },
data(){
return {
chatroom: chatroom
}
},
methods: { methods: {
sendMessage(message){ sendMessage(message){
let msg = { let msg = {
@ -60,22 +55,9 @@ export default {
} }
} }
new Vue({
el: '#app',
router,
template: '<App/>',
components: {App},
data(){
return {
chatroom: chatroom
}
}
}).$mount('#app')
const wsurl = 'ws://127.0.0.1:8090' const wsurl = 'ws://127.0.0.1:8090'
//const wsurl = 'wss://chat.adb.sh:8080'
const socket = new WebSocket(wsurl) const socket = new WebSocket(wsurl)
function element(id){ return document.getElementById(id)} function element(id){ return document.getElementById(id)}
socket.onopen = () => { socket.onopen = () => {
@ -94,15 +76,14 @@ socket.onmessage = (e) => {
console.log(`data received => ${e.data}`) console.log(`data received => ${e.data}`)
let msg = JSON.parse(e.data) let msg = JSON.parse(e.data)
if (msg.type === 'error') show_error(msg.content) if (msg.type === 'error') show_error(msg.content)
else if (msg.type === 'route') router.push({path: msg.path})
else if (msg.type === 'room'){
chatroom.user = msg.user
}
else if (msg.type === "info") chatroom.username = msg.username
else if (msg.type === 'message'){ else if (msg.type === 'message'){
chatroom.messages.push(msg) //just for now, ik it's dirty
let msgContainer = document.getElementById("messagesContainer") element('messages').innerHTML +=
if (msgContainer.scrollHeight < msgContainer.scrollTop + 1000) msgContainer.scrollTo(0, msgContainer.scrollHeight) `<div class="messageContainer" data-v-032da2b2="">
<div class="message" data-v-032da2b2="">
${msg.content.text}
</div>
</div>`;
} }
} }

View File

@ -2,15 +2,27 @@
<div> <div>
<div ref="msgContainer" id="messagesContainer" class="messagesContainer"> <div ref="msgContainer" id="messagesContainer" class="messagesContainer">
<div id="messages" class="messages"> <div id="messages" class="messages">
<p style="text-align: center; font-style: italic;">you entered the chat</p> <message msg="Hey :D" />
<div v-for="(message, i) in chatroom.messages" :key="message.time"> <message msg="Du bist blööööd xD" />
<div v-if="message.content.user !== chatroom.username && function(){ <messageReceive msg="Du auch" />
return i===0 || chatroom.messages[i-1].content.user!==message.content.user;}()" <message msg="lol" />
style="margin-left: 2rem; margin-top: 1rem">{{message.content.user}} <messageReceive msg="Du bist voll blöd, ich hasse dich, warum tust du das?!" />
</div> <message msg="Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<messageReceive v-if="message.content.user !== chatroom.username" :msg=message.content.text /> Ut imperdiet vel risus tristique mollis. Proin aliquam felis non vehicula ornare.
<message v-if="message.content.user === chatroom.username" :msg=message.content.text /> Fusce scelerisque pellentesque erat quis sollicitudin.
</div> Quisque aliquet, ligula ut volutpat vulputate, ligula lorem dictum velit, et aliquam sapien orci sed magna.
Nam suscipit ex eget urna accumsan pulvinar. Pellentesque fringilla placerat feugiat.
Aenean aliquam vestibulum metus. Nulla augue turpis, consectetur vitae quam ac, porttitor rhoncus nunc.
Nullam non turpis consequat, placerat lectus nec, ornare orci.
Fusce lorem tortor, viverra ac suscipit sit amet, scelerisque id eros.
Suspendisse et ultricies elit, vitae pretium ipsum. Suspendisse vel ex in turpis pulvinar feugiat. "
/>
<messageReceive msg="Du hast Pizza!" />
<message msg="und Kuchen :P" />
<message msg="und Kuchen :P" />
<message msg="und Kuchen :P" />
<message msg="und Kuchen :P" />
<message msg="und Kuchen :P" />
</div> </div>
</div> </div>
<newMessage /> <newMessage />
@ -23,23 +35,17 @@
import message from '@/components/message.vue'; import message from '@/components/message.vue';
import messageReceive from '@/components/messageReceive.vue'; import messageReceive from '@/components/messageReceive.vue';
import newMessage from '@/components/newMessage.vue'; import newMessage from '@/components/newMessage.vue';
import topBanner from '@/components/topBanner.vue'; import topBanner from "@/components/topBanner";
import main from '@/main.js'; import chatInformation from "@/components/chatInformation";
import ChatInformation from "@/components/chatInformation";
export default { export default {
name: 'chat', name: 'chat',
components: { components: {
ChatInformation,
message, message,
messageReceive, messageReceive,
newMessage, newMessage,
topBanner topBanner,
}, chatInformation
data(){
return {
chatroom: main.data().chatroom
}
} }
} }
</script> </script>

View File

@ -5,31 +5,23 @@
<label for="longurl-input"></label> <label for="longurl-input"></label>
<input v-model="session.content.user" class="input" id="longurl-input" type="text" autocomplete="off" maxlength="20" placeholder="chose nickname"> <input v-model="session.content.user" class="input" id="longurl-input" type="text" autocomplete="off" maxlength="20" placeholder="chose nickname">
</div> </div>
<textbtn v-on:click.native="login()" text="login" /> <input type="hidden" value="search" name="login">
<textbtn text="login" />
</div> </div>
</template> </template>
<script> <script>
import textbtn from '@/components/textbtn'; import textbtn from '@/components/textbtn';
import main from "@/main";
export default { export default {
name: "login.vue", name: "login.vue",
components: { components: {
textbtn textbtn
}, },
methods: {
login() {
if (this.session.content.user !== "") {
this.session.time = Date.now()
main.methods.sendWebSocket(this.session)
}
}
},
data(){ data(){
return { return {
session: { session: {
type: "login", type: "session",
time: Date.now(), time: Date.now(),
content: { content: {
user: "" user: ""