diff --git a/index-ca-en.html b/index-ca-en.html index d042f3894..776196094 100644 --- a/index-ca-en.html +++ b/index-ca-en.html @@ -7,6 +7,7 @@ RAMP Storylines Editor + diff --git a/index-ca-fr.html b/index-ca-fr.html index cd7a4b548..bade10c45 100644 --- a/index-ca-fr.html +++ b/index-ca-fr.html @@ -7,6 +7,7 @@ Éditeur de scénarios de la PCAR + diff --git a/index.html b/index.html index 771e2d80e..124246f37 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ + diff --git a/scripts/hack-timer/HackTimer.js b/scripts/hack-timer/HackTimer.js new file mode 100644 index 000000000..3858f7910 --- /dev/null +++ b/scripts/hack-timer/HackTimer.js @@ -0,0 +1,149 @@ +(function (workerScript) { + if (!/MSIE 10/i.test(navigator.userAgent)) { + try { + var blob = new Blob([ + "\ +var fakeIdToId = {};\ +onmessage = function (event) {\ + var data = event.data,\ + name = data.name,\ + fakeId = data.fakeId,\ + time;\ + if(data.hasOwnProperty('time')) {\ + time = data.time;\ + }\ + switch (name) {\ + case 'setInterval':\ + fakeIdToId[fakeId] = setInterval(function () {\ + postMessage({fakeId: fakeId});\ + }, time);\ + break;\ + case 'clearInterval':\ + if (fakeIdToId.hasOwnProperty (fakeId)) {\ + clearInterval(fakeIdToId[fakeId]);\ + delete fakeIdToId[fakeId];\ + }\ + break;\ + case 'setTimeout':\ + fakeIdToId[fakeId] = setTimeout(function () {\ + postMessage({fakeId: fakeId});\ + if (fakeIdToId.hasOwnProperty (fakeId)) {\ + delete fakeIdToId[fakeId];\ + }\ + }, time);\ + break;\ + case 'clearTimeout':\ + if (fakeIdToId.hasOwnProperty (fakeId)) {\ + clearTimeout(fakeIdToId[fakeId]);\ + delete fakeIdToId[fakeId];\ + }\ + break;\ + }\ +}\ +" + ]); + // Obtain a blob URL reference to our worker 'file'. + workerScript = window.URL.createObjectURL(blob); + } catch (error) { + /* Blob is not supported, use external script instead */ + } + } + var worker, + fakeIdToCallback = {}, + lastFakeId = 0, + maxFakeId = 0x7fffffff, // 2 ^ 31 - 1, 31 bit, positive values of signed 32 bit integer + logPrefix = 'HackTimer.js by turuslan: '; + if (typeof Worker !== 'undefined') { + function getFakeId() { + do { + if (lastFakeId == maxFakeId) { + lastFakeId = 0; + } else { + lastFakeId++; + } + } while (fakeIdToCallback.hasOwnProperty(lastFakeId)); + return lastFakeId; + } + try { + worker = new Worker(workerScript); + window.setInterval = function (callback, time /* , parameters */) { + var fakeId = getFakeId(); + fakeIdToCallback[fakeId] = { + callback: callback, + parameters: Array.prototype.slice.call(arguments, 2) + }; + worker.postMessage({ + name: 'setInterval', + fakeId: fakeId, + time: time + }); + return fakeId; + }; + window.clearInterval = function (fakeId) { + if (fakeIdToCallback.hasOwnProperty(fakeId)) { + delete fakeIdToCallback[fakeId]; + worker.postMessage({ + name: 'clearInterval', + fakeId: fakeId + }); + } + }; + window.setTimeout = function (callback, time /* , parameters */) { + var fakeId = getFakeId(); + fakeIdToCallback[fakeId] = { + callback: callback, + parameters: Array.prototype.slice.call(arguments, 2), + isTimeout: true + }; + worker.postMessage({ + name: 'setTimeout', + fakeId: fakeId, + time: time + }); + return fakeId; + }; + window.clearTimeout = function (fakeId) { + if (fakeIdToCallback.hasOwnProperty(fakeId)) { + delete fakeIdToCallback[fakeId]; + worker.postMessage({ + name: 'clearTimeout', + fakeId: fakeId + }); + } + }; + worker.onmessage = function (event) { + var data = event.data, + fakeId = data.fakeId, + request, + parameters, + callback; + if (fakeIdToCallback.hasOwnProperty(fakeId)) { + request = fakeIdToCallback[fakeId]; + callback = request.callback; + parameters = request.parameters; + if (request.hasOwnProperty('isTimeout') && request.isTimeout) { + delete fakeIdToCallback[fakeId]; + } + } + if (typeof callback === 'string') { + try { + callback = new Function(callback); + } catch (error) { + console.log(logPrefix + 'Error parsing callback code string: ', error); + } + } + if (typeof callback === 'function') { + callback.apply(window, parameters); + } + }; + worker.onerror = function (event) { + console.log(event); + }; + } catch (error) { + console.log(logPrefix + 'Initialisation failed'); + console.error(error); + } + } else { + console.log(logPrefix + 'Initialisation failed - HTML5 Web Worker is not supported'); + } +})('HackTimerWorker.js'); diff --git a/scripts/hack-timer/HackTimerWorker.js b/scripts/hack-timer/HackTimerWorker.js new file mode 100644 index 000000000..6742a98a6 --- /dev/null +++ b/scripts/hack-timer/HackTimerWorker.js @@ -0,0 +1,37 @@ +var fakeIdToId = {}; +onmessage = function (event) { + var data = event.data, + name = data.name, + fakeId = data.fakeId, + time; + if (data.hasOwnProperty('time')) { + time = data.time; + } + switch (name) { + case 'setInterval': + fakeIdToId[fakeId] = setInterval(function () { + postMessage({ fakeId: fakeId }); + }, time); + break; + case 'clearInterval': + if (fakeIdToId.hasOwnProperty(fakeId)) { + clearInterval(fakeIdToId[fakeId]); + delete fakeIdToId[fakeId]; + } + break; + case 'setTimeout': + fakeIdToId[fakeId] = setTimeout(function () { + postMessage({ fakeId: fakeId }); + if (fakeIdToId.hasOwnProperty(fakeId)) { + delete fakeIdToId[fakeId]; + } + }, time); + break; + case 'clearTimeout': + if (fakeIdToId.hasOwnProperty(fakeId)) { + clearTimeout(fakeIdToId[fakeId]); + delete fakeIdToId[fakeId]; + } + break; + } +}; diff --git a/server/index.js b/server/index.js index fe5e0c23a..a5169d3af 100644 --- a/server/index.js +++ b/server/index.js @@ -595,10 +595,10 @@ function logger(type, message) { const clients = new Set(); // Used to broadcast messages to all connected clients -function broadcastToClients(message){ +function broadcastToClients(message) { const payload = JSON.stringify(message); clients.forEach((client) => { - if(client.readyState === WebSocket.OPEN){ + if (client.readyState === (process.env.SERVER_CURR_ENV !== '#{CURR_ENV}#' ? WebSocket.OPEN : 1)) { logger('INFO', `Payload sent to the client`); client.send(payload); } @@ -614,7 +614,7 @@ wss.on('connection', (ws) => { // { uuid: , lock: false } ws.on('message', function (msg) { const message = JSON.parse(msg); - const {uuid, lock} = message; + const { uuid, lock } = message; if (!uuid) { ws.send(JSON.stringify({ status: 'fail', message: 'UUID not provided.' })); @@ -640,8 +640,8 @@ wss.on('connection', (ws) => { ws.send(JSON.stringify({ status: 'success', secret })); broadcastToClients({ - type:'lock', - uuid, + type: 'lock', + uuid }); } } else { @@ -663,8 +663,8 @@ wss.on('connection', (ws) => { ws.send(JSON.stringify({ status: 'success' })); broadcastToClients({ - type:'unlock', - uuid, + type: 'unlock', + uuid }); } } @@ -680,7 +680,7 @@ wss.on('connection', (ws) => { delete lockedUuids[ws.uuid]; broadcastToClients({ type: 'unlock', - uuid: ws.uuid, + uuid: ws.uuid }); } } diff --git a/src/stores/lockStore.ts b/src/stores/lockStore.ts index 234fb0d43..f05dc21d0 100644 --- a/src/stores/lockStore.ts +++ b/src/stores/lockStore.ts @@ -12,12 +12,12 @@ export const useLockStore = defineStore('lock', { result: {} as any, broadcast: undefined as BroadcastChannel | undefined, confirmationTimeout: undefined as NodeJS.Timeout | undefined, // the timer to show the session extension confirmation modal - endTimeout: undefined as NodeJS.Timeout | undefined, // the timer to kill the session due to timeout + endTimeout: undefined as NodeJS.Timeout | undefined // the timer to kill the session due to timeout }), actions: { // Opens a connection with the web socket initConnection() { - return new Promise((resolve) => { + return new Promise((resolve) => { const socketUrl = `${ import.meta.env.VITE_APP_CURR_ENV ? import.meta.env.VITE_APP_API_URL : 'http://localhost:6040' }`; @@ -37,7 +37,7 @@ export const useLockStore = defineStore('lock', { }; }); }, - // Attempts to lock a storyline for this user. + // Attempts to lock a storyline for this user. // Returns a promise that resolves if the lock was successfully fetched and rejects if it was not. async lockStoryline(uuid: string): Promise { // Stop the previous storyline's timer @@ -55,16 +55,15 @@ export const useLockStore = defineStore('lock', { const handleMessage = (event: MessageEvent) => { const data = JSON.parse(event.data); - if(data !== undefined){ - if(data.status === 'fail'){ + if (data !== undefined) { + if (data.status === 'fail') { this.socket!.removeEventListener('message', handleMessage); reject(new Error(data.message || 'Failed to lock storyline.')); - } - else if (data.status === 'success') { + } else if (data.status === 'success') { this.socket!.removeEventListener('message', handleMessage); this.uuid = uuid; - this.secret = data.secret; + this.secret = data.secret; this.broadcast = new BroadcastChannel(data.secret); resolve();