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();