Displaying location info from websocket
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"http-proxy": "^1.18.1",
|
"http-proxy": "^1.18.1",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"moment": "^2.30.1"
|
"moment": "^2.30.1",
|
||||||
|
"ws": "^8.18.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
|
import { broadcast } from './ws.js';
|
||||||
|
|
||||||
const handlers = {
|
const handlers = {
|
||||||
updateLocation(req, res) {
|
updateLocation(req, res) {
|
||||||
console.log("req received")
|
const { name, latitude, longitude, timestamp } = req.body;
|
||||||
|
console.log(`Received location: (${name}, ${latitude}, ${longitude}) at ${timestamp}`);
|
||||||
|
broadcast("update-location", { name, latitude, longitude, timestamp });
|
||||||
|
res.json({ success: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,15 +4,14 @@ import http from 'http'
|
|||||||
import chalk from 'chalk'
|
import chalk from 'chalk'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import httpProxy from 'http-proxy';
|
import { initWebSocket } from './ws.js'
|
||||||
const proxy = httpProxy.createProxyServer({});
|
|
||||||
import { fileURLToPath } from 'url';
|
|
||||||
|
|
||||||
import Database from "./db.js"
|
import Database from "./db.js"
|
||||||
import AuthHandler from './auth.js';
|
import AuthHandler from './auth.js';
|
||||||
import handlers from "./handlers.js";
|
import handlers from "./handlers.js";
|
||||||
|
|
||||||
// Get __dirname in ES6 environment
|
// Get __dirname in ES6 environment
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const __dirname = path.dirname(__filename);
|
const __dirname = path.dirname(__filename);
|
||||||
|
|
||||||
@@ -130,6 +129,7 @@ class Server {
|
|||||||
app.use('/', router);
|
app.use('/', router);
|
||||||
|
|
||||||
const server = http.createServer(app);
|
const server = http.createServer(app);
|
||||||
|
initWebSocket(server);
|
||||||
const PORT = 3008;
|
const PORT = 3008;
|
||||||
server.listen(PORT, () => {
|
server.listen(PORT, () => {
|
||||||
console.log("\n")
|
console.log("\n")
|
||||||
|
|||||||
31
server/ws.js
Normal file
31
server/ws.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import { WebSocket, WebSocketServer } from 'ws';
|
||||||
|
|
||||||
|
let wss;
|
||||||
|
|
||||||
|
export function initWebSocket(server) {
|
||||||
|
wss = new WebSocketServer({ server });
|
||||||
|
|
||||||
|
wss.on('connection', (ws, req) => {
|
||||||
|
console.log('✅ New WebSocket client connected');
|
||||||
|
|
||||||
|
ws.on('close', () => {
|
||||||
|
console.log('Client disconnected');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('WebSocket server initialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcast a message to all connected clients
|
||||||
|
export function broadcast(reqType, data) {
|
||||||
|
if (!wss) return;
|
||||||
|
|
||||||
|
const payload = typeof data === 'string' ? data : JSON.stringify(data);
|
||||||
|
const message = `${reqType}|${payload}`;
|
||||||
|
|
||||||
|
wss.clients.forEach(client => {
|
||||||
|
if (client.readyState === WebSocket.OPEN) {
|
||||||
|
client.send(message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,11 +1,19 @@
|
|||||||
|
import "./LocationList.js"
|
||||||
|
|
||||||
class Home extends Shadow {
|
class Home extends Shadow {
|
||||||
render() {
|
render() {
|
||||||
ZStack(() => {
|
ZStack(() => {
|
||||||
|
p("BLOCKCATCHER")
|
||||||
|
.x(2, em).y(1, em)
|
||||||
|
.fontSize(1.2, em)
|
||||||
|
.fontFamily("Arial")
|
||||||
|
|
||||||
|
LocationList()
|
||||||
})
|
})
|
||||||
.backgroundColor("#aebdff")
|
.backgroundColor("#aebdff")
|
||||||
.display("block")
|
.display("block")
|
||||||
.width(100, vw).height(100, vh)
|
.width(100, vw).height(100, vh)
|
||||||
|
.color("#60759f")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
26
ui/app/components/LocationList.js
Normal file
26
ui/app/components/LocationList.js
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
class LocationList extends Shadow {
|
||||||
|
list = []
|
||||||
|
|
||||||
|
render() {
|
||||||
|
VStack(() => {
|
||||||
|
this.list.forEach((update) => {
|
||||||
|
console.log(update.name)
|
||||||
|
HStack(() => {
|
||||||
|
p(update.timestamp)
|
||||||
|
p(update.name)
|
||||||
|
p(update.latitude)
|
||||||
|
p(update.longitude)
|
||||||
|
})
|
||||||
|
.gap(1, em)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.onEvent("update-location", (e) => {
|
||||||
|
console.log("location received: ", e.detail)
|
||||||
|
this.list.unshift(e.detail)
|
||||||
|
this.rerender()
|
||||||
|
})
|
||||||
|
.x(2, em).y(5, em)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.registerShadow(LocationList)
|
||||||
@@ -1,2 +1,5 @@
|
|||||||
|
import ConnectionHandler from "./ws/Connection.js"
|
||||||
|
window.ConnectionHandler = new ConnectionHandler()
|
||||||
|
|
||||||
import "./components/Home.js"
|
import "./components/Home.js"
|
||||||
Home()
|
Home()
|
||||||
120
ui/app/ws/Connection.js
Normal file
120
ui/app/ws/Connection.js
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
class Connection {
|
||||||
|
connectionTries = 0
|
||||||
|
ws;
|
||||||
|
linkCreated;
|
||||||
|
wsStatus;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
if(window.location.hostname === "localhost") {
|
||||||
|
this.ws = new WebSocket("ws://" + "localhost:3008")
|
||||||
|
} else {
|
||||||
|
this.ws = new WebSocket("wss://" + window.location.hostname + window.location.pathname)
|
||||||
|
}
|
||||||
|
this.ws.addEventListener('open', () => {
|
||||||
|
this.connectionTries = 0
|
||||||
|
console.log("Websocket connection established.");
|
||||||
|
this.ws.addEventListener('message', this.onMessage)
|
||||||
|
});
|
||||||
|
this.ws.addEventListener("close", () => {
|
||||||
|
this.checkOpen();
|
||||||
|
console.log('Websocket Closed')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onMessage = (event) => {
|
||||||
|
let message = event.data;
|
||||||
|
const [reqType, payload] = message.split('|');
|
||||||
|
|
||||||
|
switch(reqType) {
|
||||||
|
case 'update-location':
|
||||||
|
window.dispatchEvent(new CustomEvent('update-location', {detail: JSON.parse(payload)}))
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log('Websocket message:', message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async checkOpen() {
|
||||||
|
if (this.ws.readyState === WebSocket.OPEN) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
await this.sleep(this.connectionTries < 20 ? 5000 : 60000)
|
||||||
|
this.connectionTries++
|
||||||
|
console.log('Reestablishing connection')
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep = (time) => {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
setTimeout(resolve, time);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sendMessage = (msg) => {
|
||||||
|
if (this.ws.readyState === WebSocket.OPEN) {
|
||||||
|
this.ws.send(msg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('No websocket connection: Cannot send message');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCSS = async (updateStyle, newValue) => {
|
||||||
|
let currentSpace = window.wrapper.getAttribute("name").replace(/ /g,'%20')
|
||||||
|
let currentFolder = window.location.pathname;
|
||||||
|
//create the inital link
|
||||||
|
this.linkCreated = false;
|
||||||
|
let cssIncomingText = ""
|
||||||
|
Array.from(document.styleSheets).forEach(el => {
|
||||||
|
if(el?.href?.includes?.(`.${currentSpace}.css`)) {
|
||||||
|
this.linkCreated = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let currentSpaceDataAttr = window.wrapper.getAttribute("name");
|
||||||
|
let cssInit = `parchment-page[name="${currentSpaceDataAttr}"] {background-color: #e9c9a0;} parchment-page[name="${currentSpaceDataAttr}"] > p.text {font-family: ${newValue};} parchment-page[name="${currentSpaceDataAttr}"] > file-::before, parchment-page[name="${currentSpaceDataAttr}"] > image-::before, parchment-page[name="${currentSpaceDataAttr}"] > parchment-page::before {font-family: ${newValue};font-weight: 400;} parchment-page[name="${currentSpaceDataAttr}"] > space-select-outline > file-::before, parchment-page[name="${currentSpaceDataAttr}"] > select-outline > *, parchment-page[name="${currentSpaceDataAttr}"] > select-outline > image-::before ,parchment-page[name="${currentSpaceDataAttr}"] > space-select-outline > parchment-page::before, parchment-page[name="${currentSpaceDataAttr}"] > a, parchment-page[name="${currentSpaceDataAttr}"] > input-box {font-family: ${newValue}; font-weight: 400;}`
|
||||||
|
cssIncomingText += cssInit
|
||||||
|
|
||||||
|
let CSSRawData = `REQUEST|update-css|${currentFolder}|${cssIncomingText}|`
|
||||||
|
await this.checkOpen()
|
||||||
|
this.ws.send(CSSRawData)
|
||||||
|
}
|
||||||
|
|
||||||
|
createCSSLink = (wsMessage) => {
|
||||||
|
let retrieveHref = wsMessage;
|
||||||
|
var link = document.createElement("link");
|
||||||
|
link.rel = "stylesheet";
|
||||||
|
link.id = window.wrapper.getAttribute('name')+"-css"
|
||||||
|
link.href = retrieveHref;
|
||||||
|
|
||||||
|
let retrieveStyleLinks = document.querySelectorAll(`[href='${retrieveHref}']`);
|
||||||
|
if (retrieveStyleLinks[0] !== undefined) {
|
||||||
|
retrieveStyleLinks[0].remove();
|
||||||
|
}
|
||||||
|
window.wrapper.prepend(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
scrapeExternalHTMLTitle = async (href) => {
|
||||||
|
let req = `REQUEST|scrape-title|${href}|`
|
||||||
|
await this.checkOpen()
|
||||||
|
this.ws.send(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLinkTitle = (title) => {
|
||||||
|
let link = document.querySelectorAll('.convert-to-title')[0]
|
||||||
|
if (title !=="") {
|
||||||
|
link.innerHTML += title;
|
||||||
|
} else {
|
||||||
|
link.innerHTML += link.getAttribute('href')
|
||||||
|
}
|
||||||
|
link.classList.remove('convert-to-title')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Connection
|
||||||
22
ui/app/ws/ConnectionHandler.js
Normal file
22
ui/app/ws/ConnectionHandler.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import Connection from "./Connection.js";
|
||||||
|
|
||||||
|
export default class ConnectionHandler {
|
||||||
|
connection;
|
||||||
|
disabled = true;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.connection = new Connection();
|
||||||
|
}
|
||||||
|
|
||||||
|
isOpen() {
|
||||||
|
if(this.connection.checkOpen()) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
send(msg) {
|
||||||
|
this.connection.sendMessage(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user