diff --git a/src/app.js b/src/app.js index f6cd01f..90962ca 100644 --- a/src/app.js +++ b/src/app.js @@ -1,15 +1,12 @@ import { invoke } from '@tauri-apps/api/core'; +import { wsConnection } from './websocket.js'; import { reloadApp } from './AppWrapper.vue' -const HEARTBEAT_INTERVAL = 25000; export default { name: "App", data() { let token = null; - let message_ws = null; - let ms_counter = 0; - invoke('get_local_token') .then((res) => { token = JSON.parse(res)['token']; @@ -19,60 +16,8 @@ export default { let servers = JSON.parse(res); this.token = servers.token; token = servers.token; - - if(message_ws === null) { - let message_ws = new WebSocket("wss://onlinedi.vision/wss?username="+this.username); - - message_ws.addEventListener("message", (event) => { - if(ms_counter === 0 ) { - ms_counter += 1; - console.log("[WEBSOCKET] Message from server (" + ms_counter + ")", event.data); - - invoke('spellcheck', { token: token, username: this.username, key: event.data }) - .then((res) => { - message_ws.send(res); - }).catch((err) => { - console.log(err); - }); - } else if(ms_counter === 1) { - ms_counter += 1; - if(event.data === 'CONNECTED') { - console.log('[WEBSOCKET CONNECTED]'); - message_ws.send('TOKEN:'+this.token); - } - } else if (ms_counter == 2) { - ms_counter += 1; - this.token = event.data; - }else if(ms_counter > 2) { - console.log("[WEBSOCKET MESSAGE]: " + event.data); - - if(event.data == "PONG") return; - - let splitm = event.data.split(':'); - let [sid, channel, username, ...message] = splitm; - message = message.join(':'); - - this.appState[ - this.appState.findIndex(obj => obj.serverID == sid) - ]['storedChannels'][ - this.appState[ - this.appState.findIndex(obj => obj.serverID == sid) - ]['storedChannels'].findIndex(obj => obj.channelTag === channel) - ]['messages'].unshift({ - 'username': username, - 'm_content': message - }); - } - }); - message_ws.addEventListener("open", () => { - setInterval(() => { - if(message_ws.readyState === WebSocket.OPEN) { - message_ws.send('PING'); - } - }, HEARTBEAT_INTERVAL); - }); - this.ws = message_ws; - } + this.initWebsocket(token); + invoke('write_credentials', { creds: JSON.stringify({ 'username': this.username, 'token': this.token }) }); for (let i = 0; i < servers['s_list'].length; i++) { @@ -377,7 +322,7 @@ export default { let date = new Date(Number(timestamp)); let month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; - return month[Number(date.getMonth())] + ' ' + date.getDate() + ' ' + date.getFullYear() + ' ' + date.getHours() + ':' + date.getMinutes(); + return month[Number(date.getMonth())] + ' ' + date.getDate() + ' ' + date.getFullYear() + ' ' + date.getHours() + ':' + date.getMinutes().toString().padStart(2, '0'); }, create_channel() { this.createChannelPopUp = !this.createChannelPopUp; @@ -553,6 +498,32 @@ export default { }).catch((err) => { console.log(err); }) - } + }, + initWebsocket(){ + this.ws = new wsConnection(this.username); + this.ws.addEventListener("reqHandshake", () => { + this.ws.handshake(this.token).then( (res) => { this.token = res; this.ws.startReceive(); } ); + }); + this.ws.connectWebsocket(); + this.ws.addEventListener("message", this.receiveMessage); + + }, + receiveMessage(event){ + let splitm = event.detail.split(':'); + let [sid, channel, username, ...message] = splitm; + message = message.join(':'); + + this.appState[ + this.appState.findIndex(obj => obj.serverID == sid) + ]['storedChannels'][ + this.appState[ + this.appState.findIndex(obj => obj.serverID == sid) + ]['storedChannels'].findIndex(obj => obj.channelTag === channel) + ]['messages'].unshift({ + 'username': username, + 'm_content': message, + 'datetime': Date.now() + }); + } }, }; diff --git a/src/websocket.js b/src/websocket.js new file mode 100644 index 0000000..69d96bb --- /dev/null +++ b/src/websocket.js @@ -0,0 +1,75 @@ +import { invoke } from '@tauri-apps/api/core'; +const HEARTBEAT_INTERVAL = 25000; +const RECONNECT_INTERVAL = 3000; +const HANDSHAKE_LENGTH = 2; +const WEBSOCKET_URL = "wss://onlinedi.vision/wss"; + +export class wsConnection extends EventTarget{ + message_ws = null; + heartbeat = null; + username = null; + + constructor(username) { + super(); + this.username = username; + } + connectWebsocket() { + this.message_ws = new WebSocket(WEBSOCKET_URL+"?username="+this.username); + this.message_ws.addEventListener("open", () => { + this.dispatchEvent(new CustomEvent("reqHandshake")); + this.heartbeat = setInterval(() => { + if(this.message_ws.readyState === WebSocket.OPEN) { + this.message_ws.send('PING'); + } + }, HEARTBEAT_INTERVAL); + }); + this.message_ws.addEventListener("close", () => { + console.log('[WEBSOCKET CONNECTION LOST. ATTEMPTING TO RECONNECT]'); + if(this.heartbeat != null) { + clearInterval(this.heartbeat); + } + setTimeout(() => { this.connectWebsocket(); }, RECONNECT_INTERVAL); + }); + } + handshake(token, username = this.username) { + return new Promise(resolve => { + let ms_counter = 0; + function handler(event) { + if(ms_counter === 0 ) { + ms_counter += 1; + console.log("[WEBSOCKET] Message from server (" + ms_counter + ")", event.data); + invoke('spellcheck', { token: token, username: username, key: event.data }) + .then((res) => { + this.send(res); + }).catch((err) => { + console.log(err); + }); + } else if(ms_counter === 1) { + ms_counter += 1; + if(event.data === 'CONNECTED') { + console.log('[WEBSOCKET CONNECTED]'); + this.send('TOKEN:'+token); + } + } else if (ms_counter == HANDSHAKE_LENGTH) { + ms_counter += 1; + this.removeEventListener("message", handler); + resolve(event.data); + } + } + this.message_ws.addEventListener("message", handler); + } + ); + } + send(msg) { + this.message_ws.send(msg); + } + startReceive() { + this.message_ws.addEventListener("message", (event) => { + console.log("[WEBSOCKET MESSAGE]: " + event.data); + if(event.data == "PONG") return; + this.dispatchEvent(new CustomEvent("message", { + detail: event.data + })); + }); + } +} \ No newline at end of file