checkpoint

This commit is contained in:
Hri7566 2021-09-22 03:12:30 -04:00
parent b7db38b349
commit 2d185b9410
16 changed files with 220 additions and 78 deletions

@ -1,3 +1,3 @@
# chat-app
I have no idea what this will be, but it's my chunkiest setup-looking repo thingy yet.
I have no idea what this will be.

14
build/Channel.js Normal file

@ -0,0 +1,14 @@
"use strict";
exports.__esModule = true;
exports.Channel = void 0;
function isLobby(_id) {
return _id !== undefined;
}
var Channel = /** @class */ (function () {
function Channel(_id) {
this._id = _id;
this.isLobby = isLobby(this._id);
}
return Channel;
}());
exports.Channel = Channel;

@ -19,8 +19,9 @@ exports.Client = void 0;
var events_1 = require("events");
var Client = /** @class */ (function (_super) {
__extends(Client, _super);
function Client(ws) {
function Client(ws, server) {
var _this = _super.call(this) || this;
_this.server = server;
_this.ws = ws;
_this.bindEventListeners();
return _this;
@ -40,13 +41,26 @@ var Client = /** @class */ (function (_super) {
}
});
this.on('hi', function (msg) {
console.log(msg);
_this.sendArray([{
m: 'hi'
}]);
});
this.on('a', function (msg) {
if (!msg.message)
return;
_this.sendChatMessage(msg);
});
};
Client.prototype.sendArray = function (arr) {
var jmsgs = JSON.stringify(arr);
this.ws.send(jmsgs);
};
Client.prototype.sendChatMessage = function (msg) {
console.log("Received chat message: " + msg.message);
this.server.wsh.clients.forEach(function (cl, id) {
cl.sendArray([{ m: 'a', a: msg.message }]);
});
};
return Client;
}(events_1.EventEmitter));
exports.Client = Client;

@ -29,7 +29,7 @@ var Server = /** @class */ (function (_super) {
_this.bindEventListeners();
_this.logger = new Logger_1.Logger('server', chalk.green);
_this.logger.debug("port: " + PORT);
_this.wsh = new WebSocketHandler_1.WebSocketHandler();
_this.wsh = new WebSocketHandler_1.WebSocketHandler(_this);
_this.ws = new WebServer_1.WebServer(parseInt(PORT));
_this.ws.linkWebSocketServer(_this.wsh.wss);
_this.emit('start');

@ -14,33 +14,6 @@ var __extends = (this && this.__extends) || (function () {
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
exports.__esModule = true;
exports.WebSocketHandler = void 0;
var WebSocket = require("ws");
@ -50,8 +23,9 @@ var chalk = require("chalk");
var Client_1 = require("./Client");
var WebSocketHandler = /** @class */ (function (_super) {
__extends(WebSocketHandler, _super);
function WebSocketHandler() {
function WebSocketHandler(server) {
var _this = _super.call(this) || this;
_this.server = server;
_this.bindEventListeners();
_this.logger = new Logger_1.Logger('WebSocketHandler', chalk.yellow);
_this.clients = new Map();
@ -66,40 +40,18 @@ var WebSocketHandler = /** @class */ (function (_super) {
});
this.on('startwss', function () {
_this.logger.log('Starting WebSocket server...');
var clientIDGetter = _this.generateClientMapID();
var nextClientID = 0;
_this.wss = new WebSocket.Server({
noServer: true
});
_this.wss.on('connection', function (ws, req) {
_this.clients.set(clientIDGetter.next().value, new Client_1.Client(ws));
_this.clients.set(nextClientID++, new Client_1.Client(ws, _this.server));
});
_this.wss.on('close', function () {
_this.logger.warn('WebSocket server closed.');
});
});
};
WebSocketHandler.prototype.generateClientMapID = function () {
var i;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, 0];
case 1:
_a.sent();
i = 0;
_a.label = 2;
case 2:
if (!i) return [3 /*break*/, 5];
return [4 /*yield*/, i];
case 3:
_a.sent();
_a.label = 4;
case 4:
i++;
return [3 /*break*/, 2];
case 5: return [2 /*return*/];
}
});
};
return WebSocketHandler;
}(events_1.EventEmitter));
exports.WebSocketHandler = WebSocketHandler;

1
dist/index.html vendored

@ -7,6 +7,7 @@
<title>Document</title>
<script defer src="index.js"></script></head>
<body>
<div id="motd"></div>
<div id="chat">
<div id="chat-messages"></div>
<input type="text" name="chat-input" id="chat-input" class="chat-input" placeholder="You can type here to chat.">

33
dist/index.js vendored

File diff suppressed because one or more lines are too long

@ -8,7 +8,8 @@
"start": "node .",
"build": "yarn build-webpack && yarn build-ts",
"build-webpack": "npx webpack",
"build-ts": "npx tsc"
"build-ts": "npx tsc",
"test": "yarn build && yarn start"
},
"dependencies": {
"@types/jquery": "^3.5.6",

24
src/Channel.ts Normal file

@ -0,0 +1,24 @@
import { Client } from "./Client";
type ChannelID = `${string}`;
type LobbyID = `lobby${string}` | `test/${string}`;
function isLobby(_id: ChannelID | LobbyID): _id is LobbyID {
return _id !== undefined;
}
class Channel {
_id: ChannelID | LobbyID;
connectedClients: Client[];
isLobby: boolean;
constructor (_id: string) {
this._id = _id;
this.isLobby = isLobby(this._id);
}
}
export {
Channel
}

@ -1,12 +1,15 @@
import { EventEmitter } from 'events';
import WebSocket = require('ws');
import { Server } from './Server';
class Client extends EventEmitter {
ws: WebSocket;
server: Server;
constructor (ws: WebSocket) {
constructor (ws: WebSocket, server: Server) {
super();
this.server = server;
this.ws = ws;
this.bindEventListeners();
@ -25,14 +28,32 @@ class Client extends EventEmitter {
});
this.on('hi', msg => {
this.emit('hi');
this.sendArray([{
m: 'hi'
}]);
});
this.on('a', msg => {
if (!msg.message) return;
this.sendChatMessage(msg);
});
// TODO user data, other messages, maybe cursors
}
sendArray(arr) {
let jmsgs = JSON.stringify(arr);
this.ws.send(jmsgs);
}
sendChatMessage(msg) { // TODO move this to Channel
console.log(`Received chat message: ${msg.message}`);
this.server.wsh.clients.forEach((cl, id) => {
cl.sendArray([{m:'a', a: msg.message}])
});
}
}
export {

@ -20,7 +20,7 @@ class Server extends EventEmitter {
this.logger = new Logger('server', chalk.green);
this.logger.debug(`port: ${PORT}`);
this.wsh = new WebSocketHandler();
this.wsh = new WebSocketHandler(this);
this.ws = new WebServer(parseInt(PORT));
this.ws.linkWebSocketServer(this.wsh.wss);

@ -3,15 +3,18 @@ import { EventEmitter } from 'events';
import { Logger } from './Logger';
import chalk = require('chalk');
import { Client } from './Client';
import { Server } from './Server';
class WebSocketHandler extends EventEmitter {
wss: WebSocket.Server;
logger: Logger;
clients: Map<number, Client>;
server: Server;
constructor () {
constructor (server: Server) {
super();
this.server = server;
this.bindEventListeners();
this.logger = new Logger('WebSocketHandler', chalk.yellow);
@ -28,14 +31,14 @@ class WebSocketHandler extends EventEmitter {
this.on('startwss', () => {
this.logger.log('Starting WebSocket server...');
let clientIDGetter = this.generateClientMapID();
let nextClientID = 0
this.wss = new WebSocket.Server({
noServer: true
});
this.wss.on('connection', (ws, req) => {
this.clients.set((clientIDGetter.next().value as any), new Client(ws));
this.clients.set(nextClientID++, new Client(ws, this.server));
});
this.wss.on('close', () => {
@ -43,13 +46,6 @@ class WebSocketHandler extends EventEmitter {
});
});
}
* generateClientMapID() {
yield 0;
for (let i = 0; i; i++) {
yield i;
}
}
}
export {

@ -30,6 +30,20 @@ class Client extends EventEmitter {
m: 'hi'
}]);
});
this.ws.addEventListener('close', evt => {
console.log('WebSocket disconnected');
if (this.started) {
setTimeout(() => {
this.emit('motd', 'Connecting...');
this.connect();
}, 1000);
} else {
this.ws = undefined;
this.emit('motd', 'Offline');
return;
}
});
}
stop() {
@ -45,7 +59,7 @@ class Client extends EventEmitter {
bindEventListeners() {
this.on('hi', msg => {
console.log(msg);
'motd' in msg ? this.emit('motd', msg.motd) : this.emit('motd', 'Connected');
});
this.ws.addEventListener('message', evt => {

@ -7,6 +7,7 @@
<title>Document</title>
</head>
<body>
<div id="motd"></div>
<div id="chat">
<div id="chat-messages"></div>
<input type="text" name="chat-input" id="chat-input" class="chat-input" placeholder="You can type here to chat.">

@ -1,5 +1,8 @@
import { Client } from "./Client";
import "./style.scss";
import * as $ from "jquery";
(globalThis as any)['$'] = $;
(() => {
let secure = globalThis.location.protocol == "https";
@ -12,6 +15,65 @@ import "./style.scss";
gClient.start();
gClient.on('motd', async message => {
let motd = $("#motd");
motd.fadeOut(() => {
motd.html(message).fadeIn();
});
});
let chat = {
send: (txt: string | number | string[]) => {
console.log(`Sending chat message: ${txt}`);
gClient.sendArray([{
m: 'a',
message: txt
}]);
},
receive: (msg: any) => {
// TODO write chat receive
if (!msg.a) return;
let nameDiv = `<div class="chat-name"></div>`
let messageDiv = `<div class="chat-message"></div>`
let li = `<li>Anonymous: ${msg.a}</li>`;
$('#chat-messages').append(li);
}
}
document.addEventListener('keydown', evt => {
if (evt.code == 'Enter' || evt.code == 'Escape') {
let chatInput = $("#chat-input");
let chatFocused = chatInput.is(':focus');
if (chatFocused == true) {
if (evt.code == 'Enter') {
let text = chatInput.val();
if (text !== '') {
chat.send(text);
chatInput.val('');
}
}
chatInput.trigger('blur');
} else {
chatInput.trigger('focus');
}
}
});
gClient.on('a', msg => {
if (!msg.a) return;
console.log(`Received chat message: ${msg.a}`);
chat.receive(msg);
});
(globalThis as any).app = {
client: gClient
}

@ -19,7 +19,10 @@ body {
margin-left: 1.5%;
#chat-messages {
.chat-message {
display: inline;
list-style: none;
}
}
#chat-input {
@ -28,3 +31,21 @@ body {
-moz-box-sizing: border-box;
}
}
.spin {
animation: spin 1s linear infinite;
-webkit-animation: spin 1s linear infinite;
-moz-animation: spin 1s linear infinite;
-o-animation: spin 1s linear infinite;
-ms-animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
-webkit-transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
}
}