Compare commits
5 commits
53258703e1
...
e32eabea1f
Author | SHA1 | Date | |
---|---|---|---|
flash | e32eabea1f | ||
flash | b37352534b | ||
flash | 9f61c0d4b9 | ||
flash | f50785a209 | ||
flash | bc859a042d |
110
src/mami.js/conman.js
Normal file
110
src/mami.js/conman.js
Normal file
|
@ -0,0 +1,110 @@
|
|||
#include eventtarget.js
|
||||
#include utility.js
|
||||
|
||||
const MamiConnectionManager = function(urls) {
|
||||
if(!Array.isArray(urls))
|
||||
throw 'urls must be an array';
|
||||
|
||||
const eventTarget = new MamiEventTarget('mami:conn');
|
||||
const delays = [0, 2000, 2000, 2000, 5000, 5000, 5000, 5000, 5000, 10000, 10000, 10000, 10000, 10000, 15000, 30000, 45000, 60000, 120000, 300000];
|
||||
|
||||
let timeout;
|
||||
let attempts, started, delay, url;
|
||||
let attemptConnect;
|
||||
let startResolve;
|
||||
|
||||
const resetTimeout = () => {
|
||||
if(timeout !== undefined) {
|
||||
clearTimeout(timeout);
|
||||
timeout = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
const clear = () => {
|
||||
resetTimeout();
|
||||
attempts = started = delay = 0;
|
||||
url = undefined;
|
||||
};
|
||||
|
||||
$as(urls);
|
||||
|
||||
const onFailure = ex => {
|
||||
++attempts;
|
||||
delay = attempts < delays.length ? delays[attempts] : delays[delays.length - 1];
|
||||
|
||||
eventTarget.dispatch('fail', {
|
||||
url: url,
|
||||
started: started,
|
||||
attempt: attempts,
|
||||
delay: delay,
|
||||
error: ex,
|
||||
});
|
||||
|
||||
attempt();
|
||||
};
|
||||
|
||||
const attempt = () => {
|
||||
started = Date.now();
|
||||
url = urls[attempts % urls.length];
|
||||
|
||||
const attempt = attempts + 1;
|
||||
|
||||
timeout = setTimeout(() => {
|
||||
resetTimeout();
|
||||
|
||||
eventTarget.dispatch('attempt', {
|
||||
url: url,
|
||||
started: started,
|
||||
attempt: attempt,
|
||||
});
|
||||
|
||||
attemptConnect(url).then(result => {
|
||||
if(typeof result === 'boolean' && !result) {
|
||||
onFailure();
|
||||
return;
|
||||
}
|
||||
|
||||
eventTarget.dispatch('success', {
|
||||
url: url,
|
||||
started: started,
|
||||
attempt: attempt,
|
||||
});
|
||||
|
||||
startResolve();
|
||||
startResolve = undefined;
|
||||
attemptConnect = undefined;
|
||||
}).catch(ex => onFailure(ex));
|
||||
}, delay);
|
||||
};
|
||||
|
||||
const isActive = () => timeout !== undefined || startResolve !== undefined;
|
||||
|
||||
return {
|
||||
isActive: isActive,
|
||||
start: body => {
|
||||
return new Promise(resolve => {
|
||||
if(typeof body !== 'function')
|
||||
throw 'body must be a function';
|
||||
if(isActive())
|
||||
throw 'already attempting to connect';
|
||||
|
||||
attemptConnect = body;
|
||||
startResolve = resolve;
|
||||
|
||||
clear();
|
||||
attempt();
|
||||
});
|
||||
},
|
||||
force: () => {
|
||||
if(!isActive())
|
||||
return;
|
||||
|
||||
resetTimeout();
|
||||
delay = 0;
|
||||
attempt();
|
||||
},
|
||||
clear: clear,
|
||||
watch: eventTarget.watch,
|
||||
unwatch: eventTarget.unwatch,
|
||||
};
|
||||
};
|
22
src/mami.js/eventtarget.js
Normal file
22
src/mami.js/eventtarget.js
Normal file
|
@ -0,0 +1,22 @@
|
|||
const MamiEventTarget = function(prefix) {
|
||||
prefix = typeof prefix === 'string' ? `${prefix}:` : '';
|
||||
|
||||
const eventTarget = new EventTarget;
|
||||
const createEvent = (name, detail) => new CustomEvent(prefix + name, (typeof detail === 'object' && detail !== null && 'detail' in detail ? detail : { detail: detail }));
|
||||
|
||||
return {
|
||||
create: createEvent,
|
||||
|
||||
addEventListener: eventTarget.addEventListener.bind(eventTarget),
|
||||
removeEventListener: eventTarget.removeEventListener.bind(eventTarget),
|
||||
dispatchEvent: eventTarget.dispatchEvent.bind(eventTarget),
|
||||
|
||||
watch: (name, ...args) => {
|
||||
eventTarget.addEventListener(prefix + name, ...args);
|
||||
},
|
||||
unwatch: (name, ...args) => {
|
||||
eventTarget.removeEventListener(prefix + name, ...args);
|
||||
},
|
||||
dispatch: (...args) => eventTarget.dispatchEvent(createEvent(...args)),
|
||||
};
|
||||
};
|
|
@ -5,6 +5,7 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
#include channels.js
|
||||
#include common.js
|
||||
#include compat.js
|
||||
#include conman.js
|
||||
#include context.js
|
||||
#include emotes.js
|
||||
#include message.js
|
||||
|
@ -150,8 +151,8 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
settings.virtualise('soundEnable');
|
||||
}
|
||||
|
||||
settings.watch('soundEnable', (v, n, i) => {
|
||||
if(v) {
|
||||
settings.watch('soundEnable', ev => {
|
||||
if(ev.detail.value) {
|
||||
if(!soundCtx.ready)
|
||||
soundCtx.reset();
|
||||
|
||||
|
@ -161,22 +162,22 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
soundCtx.library.play(soundCtx.pack.getEventSound('server'));
|
||||
}
|
||||
|
||||
soundCtx.muted = !v;
|
||||
soundCtx.muted = !ev.detail.value;
|
||||
});
|
||||
|
||||
settings.watch('soundPack', (v, n, i) => {
|
||||
settings.watch('soundPack', ev => {
|
||||
const packs = soundCtx.packs;
|
||||
if(!packs.has(v)) {
|
||||
settings.delete(n);
|
||||
if(!packs.has(ev.detail.value)) {
|
||||
settings.delete(ev.detail.name);
|
||||
return;
|
||||
}
|
||||
|
||||
soundCtx.pack = packs.get(v);
|
||||
if(!i) soundCtx.library.play(soundCtx.pack.getEventSound('server'));
|
||||
soundCtx.pack = packs.get(ev.detail.value);
|
||||
if(!ev.detail.initial) soundCtx.library.play(soundCtx.pack.getEventSound('server'));
|
||||
});
|
||||
|
||||
settings.watch('soundVolume', v => {
|
||||
soundCtx.volume = v / 100;
|
||||
settings.watch('soundVolume', ev => {
|
||||
soundCtx.volume = ev.detail.value / 100;
|
||||
})
|
||||
|
||||
|
||||
|
@ -220,14 +221,16 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
loadingOverlay.setMessage('Preparing UI...');
|
||||
|
||||
const textTriggers = new MamiTextTriggers;
|
||||
const conMan = new MamiConnectionManager(futami.get('servers'));
|
||||
|
||||
// define this as late as possible'
|
||||
// define this as late as possible
|
||||
const ctx = new MamiContext({
|
||||
settings: settings,
|
||||
views: views,
|
||||
sound: soundCtx,
|
||||
textTriggers: textTriggers,
|
||||
eeprom: eeprom,
|
||||
conMan: conMan,
|
||||
});
|
||||
Object.defineProperty(window, 'mami', { enumerable: true, value: ctx });
|
||||
|
||||
|
@ -238,28 +241,28 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
Umi.UI.View.AccentReload();
|
||||
Umi.UI.Hooks.AddHooks();
|
||||
|
||||
settings.watch('style', (v, n, i) => { if(!i) Umi.UI.View.AccentReload(); });
|
||||
settings.watch('compactView', (v, n, i) => { if(!i) Umi.UI.View.AccentReload(); });
|
||||
settings.watch('preventOverflow', v => document.body.classList.toggle('prevent-overflow', v));
|
||||
settings.watch('tmpDisableOldThemeSys', (v, n, i) => { if(!i) Umi.UI.View.AccentReload(); });
|
||||
settings.watch('style', ev => { if(!ev.detail.initial) Umi.UI.View.AccentReload(); });
|
||||
settings.watch('compactView', ev => { if(!ev.detail.initial) Umi.UI.View.AccentReload(); });
|
||||
settings.watch('preventOverflow', ev => document.body.classList.toggle('prevent-overflow', ev.detail.value));
|
||||
settings.watch('tmpDisableOldThemeSys', ev => { if(!ev.detail.initial) Umi.UI.View.AccentReload(); });
|
||||
|
||||
settings.watch('minecraft', (v, n, i) => {
|
||||
if(i && v === 'no')
|
||||
settings.watch('minecraft', ev => {
|
||||
if(ev.detail.initial && ev.detail.value === 'no')
|
||||
return;
|
||||
|
||||
soundCtx.library.play((() => {
|
||||
if(i)
|
||||
return 'minecraft:nether:enter';
|
||||
if(v === 'yes')
|
||||
if(ev.detail.value === 'yes')
|
||||
return 'minecraft:door:open';
|
||||
if(v === 'old')
|
||||
if(ev.detail.value === 'old')
|
||||
return 'minecraft:door:open-old';
|
||||
return soundCtx.pack.getEventSound('join');
|
||||
})());
|
||||
});
|
||||
|
||||
settings.watch('enableNotifications', v => {
|
||||
if(!v || !('Notification' in window)
|
||||
settings.watch('enableNotifications', ev => {
|
||||
if(!ev.detail.value || !('Notification' in window)
|
||||
|| (Notification.permission === 'granted' && Notification.permission !== 'denied'))
|
||||
return;
|
||||
|
||||
|
@ -270,20 +273,20 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
});
|
||||
});
|
||||
|
||||
settings.watch('playJokeSounds', v => {
|
||||
if(!v) return;
|
||||
settings.watch('playJokeSounds', ev => {
|
||||
if(!ev.detail.value) return;
|
||||
|
||||
if(!textTriggers.hasTriggers())
|
||||
futami.getJson('texttriggers').then(trigInfos => textTriggers.addTriggers(trigInfos));
|
||||
});
|
||||
|
||||
settings.watch('weeaboo', v => {
|
||||
if(v) Weeaboo.init();
|
||||
settings.watch('weeaboo', ev => {
|
||||
if(ev.detail.value) Weeaboo.init();
|
||||
});
|
||||
|
||||
settings.watch('osuKeysV2', (v, n, i) => {
|
||||
settings.watch('osuKeysV2', ev => {
|
||||
// migrate old value
|
||||
if(i) {
|
||||
if(ev.detail.initial) {
|
||||
if(settings.has('osuKeys')) {
|
||||
settings.set('osuKeysV2', settings.get('osuKeys') ? 'yes' : 'no');
|
||||
settings.delete('osuKeys');
|
||||
|
@ -291,8 +294,8 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
}
|
||||
}
|
||||
|
||||
OsuKeys.setEnable(v !== 'no');
|
||||
OsuKeys.setRandomRate(v === 'rng');
|
||||
OsuKeys.setEnable(ev.detail.value !== 'no');
|
||||
OsuKeys.setRandomRate(ev.detail.value === 'rng');
|
||||
});
|
||||
|
||||
|
||||
|
@ -356,8 +359,8 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
settings.toggle('autoScroll');
|
||||
}
|
||||
}, 'Autoscroll');
|
||||
settings.watch('autoScroll', function(value) {
|
||||
Umi.UI.Toggles.Get('scroll').classList[value ? 'remove' : 'add']('sidebar__selector-mode--scroll-off');
|
||||
settings.watch('autoScroll', ev => {
|
||||
Umi.UI.Toggles.Get('scroll').classList.toggle('sidebar__selector-mode--scroll-off', !ev.detail.value);
|
||||
});
|
||||
|
||||
if(window.innerWidth < 768)
|
||||
|
@ -368,8 +371,8 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
settings.toggle('soundEnable');
|
||||
}
|
||||
}, 'Sounds');
|
||||
settings.watch('soundEnable', function(value) {
|
||||
Umi.UI.Toggles.Get('audio').classList[value ? 'remove' : 'add']('sidebar__selector-mode--audio-off');
|
||||
settings.watch('soundEnable', ev => {
|
||||
Umi.UI.Toggles.Get('audio').classList.toggle('sidebar__selector-mode--audio-off', !ev.detail.value);
|
||||
});
|
||||
|
||||
Umi.UI.Toggles.Add('unembed', {
|
||||
|
@ -534,11 +537,15 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
Umi.UI.InputMenus.Add('markup', 'BB Code');
|
||||
Umi.UI.InputMenus.Add('emotes', 'Emoticons');
|
||||
|
||||
let isUnloading = false;
|
||||
|
||||
window.addEventListener('beforeunload', function(ev) {
|
||||
if(settings.get('closeTabConfirm')) {
|
||||
ev.preventDefault();
|
||||
return ev.returnValue = 'Are you sure you want to close the tab?';
|
||||
}
|
||||
|
||||
isUnloading = true;
|
||||
});
|
||||
|
||||
|
||||
|
@ -572,7 +579,7 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
'_1008': 'Your client did something the server did not agree with.',
|
||||
'_1009': 'Your client sent too much data to the server at once.',
|
||||
'_1011': 'Something went wrong on the server side.',
|
||||
'_1012': 'The server is restarting, reconnecting soon...',
|
||||
'_1012': 'The chat server is restarting.',
|
||||
'_1013': 'You cannot connect to the server right now, try again later.',
|
||||
'_1015': 'Your client and the server could not establish a secure connection.',
|
||||
};
|
||||
|
@ -583,12 +590,12 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
'joinfail': 'You are banned.',
|
||||
};
|
||||
|
||||
const sockChat = new Umi.Protocol.SockChat.Protocol;
|
||||
const sockChat = new Umi.Protocol.SockChat.Protocol(futami.get('ping') * 1000);
|
||||
MamiCompat('Umi.Server', { get: () => sockChat, configurable: true });
|
||||
|
||||
let dumpEvents = false;
|
||||
settings.watch('dumpEvents', value => dumpEvents = value);
|
||||
settings.watch('dumpPackets', value => sockChat.setDumpPackets(value));
|
||||
settings.watch('dumpEvents', ev => dumpEvents = ev.detail.value);
|
||||
settings.watch('dumpPackets', ev => sockChat.setDumpPackets(ev.detail.value));
|
||||
|
||||
Umi.UI.Hooks.SetCallbacks(sockChat.sendMessage, sockChat.switchChannel);
|
||||
|
||||
|
@ -596,60 +603,80 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
MamiCompat('Umi.Protocol.SockChat.Protocol.Instance.SendMessage', { value: text => sockChat.sendMessage(text), configurable: true });
|
||||
MamiCompat('Umi.Protocol.SockLegacy.Protocol.Instance.SendMessage', { value: text => sockChat.sendMessage(text), configurable: true });
|
||||
|
||||
sockChat.watch('conn:init', init => {
|
||||
if(dumpEvents) console.log('conn:init', init);
|
||||
sockChat.watch('conn:lost', ev => {
|
||||
if(dumpEvents) console.log('conn:lost', ev);
|
||||
|
||||
let message = 'Connecting to server...';
|
||||
if(init.attempt > 2)
|
||||
message += ` (Attempt ${connectAttempts})`;
|
||||
if(conMan.isActive() || isUnloading)
|
||||
return;
|
||||
|
||||
getLoadingOverlay('spinner', 'Loading...', message);
|
||||
});
|
||||
sockChat.watch('conn:ready', ready => {
|
||||
if(dumpEvents) console.log('conn:ready', ready);
|
||||
const errorCode = ev.detail.code;
|
||||
const isRestarting = ev.detail.isRestarting;
|
||||
|
||||
getLoadingOverlay('spinner', 'Loading...', 'Authenticating...');
|
||||
pingToggle.title = '∞ms';
|
||||
pingIndicator.setStrength(-1);
|
||||
|
||||
const authInfo = MamiMisuzuAuth.getInfo();
|
||||
sockChat.sendAuth(authInfo.method, authInfo.token);
|
||||
});
|
||||
sockChat.watch('conn:lost', lost => {
|
||||
if(dumpEvents) console.log('conn:lost', lost);
|
||||
const conManAttempt = ev => {
|
||||
if(isRestarting || ev.detail.attempt > 1) {
|
||||
let message = ev.detail.attempt > 2 ? `Attempt ${ev.detail.attempt}...` : 'Connecting to server...';
|
||||
getLoadingOverlay('spinner', 'Connecting...', message);
|
||||
}
|
||||
};
|
||||
const conManFail = ev => {
|
||||
if(isRestarting || ev.detail.attempt > 1) {
|
||||
let header = isRestarting ? 'Restarting...' : 'Disconnected';
|
||||
let message = wsCloseReasons[`_${errorCode}`] ?? `Something caused an unexpected connection loss. (${errorCode})`;
|
||||
|
||||
getLoadingOverlay(
|
||||
'unlink', 'Disconnected!',
|
||||
wsCloseReasons[`_${lost.code}`] ?? `Something caused an unexpected connection loss. (${lost.code})`
|
||||
);
|
||||
});
|
||||
sockChat.watch('conn:error', error => {
|
||||
console.error('conn:error', error);
|
||||
if(ev.detail.delay > 0)
|
||||
message += ` Retrying in ${ev.detail.delay / 1000} seconds...`;
|
||||
|
||||
// this is absolutely disgusting but i really don't care right now sorry
|
||||
message += ' <a href="javascript:void(0)" onclick="mami.conMan.force()">Retry now</a>';
|
||||
|
||||
getLoadingOverlay('unlink', header, message);
|
||||
}
|
||||
};
|
||||
|
||||
conMan.watch('attempt', conManAttempt);
|
||||
conMan.watch('fail', conManFail);
|
||||
|
||||
conMan.start(async url => {
|
||||
await sockChat.open(url);
|
||||
}).then(() => {
|
||||
conMan.unwatch('attempt', conManAttempt);
|
||||
conMan.unwatch('fail', conManFail);
|
||||
|
||||
pingToggle.title = 'Ready~';
|
||||
pingIndicator.setStrength(3);
|
||||
|
||||
const authInfo = MamiMisuzuAuth.getInfo();
|
||||
sockChat.sendAuth(authInfo.method, authInfo.token);
|
||||
});
|
||||
});
|
||||
|
||||
sockChat.watch('ping:send', send => {
|
||||
if(dumpEvents) console.log('ping:send', send);
|
||||
sockChat.watch('ping:send', ev => {
|
||||
if(dumpEvents) console.log('ping:send', ev);
|
||||
});
|
||||
sockChat.watch('ping:long', long => {
|
||||
if(dumpEvents) console.log('ping:long', long);
|
||||
sockChat.watch('ping:long', ev => {
|
||||
if(dumpEvents) console.log('ping:long', ev);
|
||||
|
||||
pingToggle.title = '+2000ms';
|
||||
pingIndicator.setStrength(0);
|
||||
});
|
||||
sockChat.watch('ping:recv', recv => {
|
||||
if(dumpEvents) console.log('ping:recv', recv);
|
||||
sockChat.watch('ping:recv', ev => {
|
||||
if(dumpEvents) console.log('ping:recv', ev);
|
||||
|
||||
let strength = 3;
|
||||
if(recv.diff >= 1000) --strength;
|
||||
if(recv.diff >= 250) --strength;
|
||||
if(ev.detail.diff >= 1000) --strength;
|
||||
if(ev.detail.diff >= 250) --strength;
|
||||
|
||||
pingToggle.title = `${recv.diff.toLocaleString()}ms`;
|
||||
pingToggle.title = `${ev.detail.diff.toLocaleString()}ms`;
|
||||
pingIndicator.setStrength(strength);
|
||||
});
|
||||
|
||||
sockChat.watch('session:start', ev => {
|
||||
if(dumpEvents) console.log('session:start', ev);
|
||||
|
||||
sockChat.watch('session:start', start => {
|
||||
if(dumpEvents) console.log('session:start', start);
|
||||
|
||||
const userInfo = new Umi.User(start.user.id, start.user.name, start.user.colour, start.user.permsRaw);
|
||||
const userInfo = new Umi.User(ev.detail.user.id, ev.detail.user.name, ev.detail.user.colour, ev.detail.user.permsRaw);
|
||||
Umi.User.setCurrentUser(userInfo);
|
||||
Umi.Users.Add(userInfo);
|
||||
|
||||
|
@ -657,102 +684,103 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
Umi.UI.Emoticons.Init();
|
||||
Umi.Parsing.Init();
|
||||
|
||||
views.pop(ctx => MamiAnimate({
|
||||
async: true,
|
||||
duration: 120,
|
||||
easing: 'inOutSine',
|
||||
start: () => {
|
||||
ctx.toElem.style.zIndex = '100';
|
||||
ctx.fromElem.style.pointerEvents = 'none';
|
||||
ctx.fromElem.style.zIndex = '200';
|
||||
},
|
||||
update: t => {
|
||||
ctx.fromElem.style.transform = `scale(${1 + (.25 * t)})`;
|
||||
ctx.fromElem.style.opacity = 1 - (1 * t).toString();
|
||||
},
|
||||
end: () => {
|
||||
ctx.toElem.style.zIndex = null;
|
||||
},
|
||||
}));
|
||||
if(views.count() > 1)
|
||||
views.pop(ctx => MamiAnimate({
|
||||
async: true,
|
||||
duration: 120,
|
||||
easing: 'inOutSine',
|
||||
start: () => {
|
||||
ctx.toElem.style.zIndex = '100';
|
||||
ctx.fromElem.style.pointerEvents = 'none';
|
||||
ctx.fromElem.style.zIndex = '200';
|
||||
},
|
||||
update: t => {
|
||||
ctx.fromElem.style.transform = `scale(${1 + (.25 * t)})`;
|
||||
ctx.fromElem.style.opacity = 1 - (1 * t).toString();
|
||||
},
|
||||
end: () => {
|
||||
ctx.toElem.style.zIndex = null;
|
||||
},
|
||||
}));
|
||||
});
|
||||
sockChat.watch('session:fail', fail => {
|
||||
if(dumpEvents) console.log('session:fail', fail);
|
||||
sockChat.watch('session:fail', ev => {
|
||||
if(dumpEvents) console.log('session:fail', ev);
|
||||
|
||||
if(fail.baka !== undefined) {
|
||||
new MamiForceDisconnectNotice(fail.baka).pushOn(views);
|
||||
if(ev.detail.baka !== undefined) {
|
||||
new MamiForceDisconnectNotice(ev.detail.baka).pushOn(views);
|
||||
return;
|
||||
}
|
||||
|
||||
getLoadingOverlay(
|
||||
'cross', 'Failed!',
|
||||
sessFailReasons[fail.session.reason] ?? `Unknown reason: ${fail.session.reason}`
|
||||
sessFailReasons[ev.detail.session.reason] ?? `Unknown reason: ${ev.detail.session.reason}`
|
||||
);
|
||||
|
||||
if(fail.session.needsAuth)
|
||||
if(ev.detail.session.needsAuth)
|
||||
setTimeout(() => location.assign(futami.get('login')), 1000);
|
||||
});
|
||||
sockChat.watch('session:term', term => {
|
||||
if(dumpEvents) console.log('session:term', term);
|
||||
sockChat.watch('session:term', ev => {
|
||||
if(dumpEvents) console.log('session:term', ev);
|
||||
|
||||
new MamiForceDisconnectNotice(term.baka).pushOn(views);
|
||||
new MamiForceDisconnectNotice(ev.detail.baka).pushOn(views);
|
||||
});
|
||||
|
||||
sockChat.watch('user:add', add => {
|
||||
if(dumpEvents) console.log('user:add', add);
|
||||
sockChat.watch('user:add', ev => {
|
||||
if(dumpEvents) console.log('user:add', ev);
|
||||
|
||||
if(add.user.self)
|
||||
if(ev.detail.user.self)
|
||||
return;
|
||||
|
||||
const userInfo = new Umi.User(add.user.id, add.user.name, add.user.colour, add.user.permsRaw);
|
||||
const userInfo = new Umi.User(ev.detail.user.id, ev.detail.user.name, ev.detail.user.colour, ev.detail.user.permsRaw);
|
||||
Umi.Users.Add(userInfo);
|
||||
|
||||
if(add.msg !== undefined)
|
||||
if(ev.detail.msg !== undefined)
|
||||
Umi.Messages.Add(new Umi.Message(
|
||||
add.msg.id, add.msg.time, undefined, '', add.msg.channel, false,
|
||||
ev.detail.msg.id, ev.detail.msg.time, undefined, '', ev.detail.msg.channel, false,
|
||||
{
|
||||
isError: false,
|
||||
type: add.msg.botInfo.type,
|
||||
args: add.msg.botInfo.args,
|
||||
type: ev.detail.msg.botInfo.type,
|
||||
args: ev.detail.msg.botInfo.args,
|
||||
target: userInfo,
|
||||
}
|
||||
));
|
||||
});
|
||||
sockChat.watch('user:remove', remove => {
|
||||
if(dumpEvents) console.log('user:remove', remove);
|
||||
sockChat.watch('user:remove', ev => {
|
||||
if(dumpEvents) console.log('user:remove', ev);
|
||||
|
||||
const userInfo = Umi.Users.Get(remove.user.id);
|
||||
const userInfo = Umi.Users.Get(ev.detail.user.id);
|
||||
if(userInfo === null)
|
||||
return;
|
||||
|
||||
if(remove.msg !== undefined)
|
||||
if(ev.detail.msg !== undefined)
|
||||
Umi.Messages.Add(new Umi.Message(
|
||||
remove.msg.id,
|
||||
remove.msg.time,
|
||||
ev.detail.msg.id,
|
||||
ev.detail.msg.time,
|
||||
undefined,
|
||||
'',
|
||||
remove.msg.channel,
|
||||
ev.detail.msg.channel,
|
||||
false,
|
||||
{
|
||||
isError: false,
|
||||
type: remove.msg.botInfo.type,
|
||||
args: remove.msg.botInfo.args,
|
||||
type: ev.detail.msg.botInfo.type,
|
||||
args: ev.detail.msg.botInfo.args,
|
||||
target: userInfo,
|
||||
},
|
||||
));
|
||||
|
||||
Umi.Users.Remove(userInfo);
|
||||
});
|
||||
sockChat.watch('user:update', update => {
|
||||
if(dumpEvents) console.log('user:update', update);
|
||||
sockChat.watch('user:update', ev => {
|
||||
if(dumpEvents) console.log('user:update', ev);
|
||||
|
||||
const userInfo = Umi.Users.Get(update.user.id);
|
||||
userInfo.setName(update.user.name);
|
||||
userInfo.setColour(update.user.colour);
|
||||
userInfo.setPermissions(update.user.permsRaw);
|
||||
const userInfo = Umi.Users.Get(ev.detail.user.id);
|
||||
userInfo.setName(ev.detail.user.name);
|
||||
userInfo.setColour(ev.detail.user.colour);
|
||||
userInfo.setPermissions(ev.detail.user.permsRaw);
|
||||
Umi.Users.Update(userInfo.getId(), userInfo);
|
||||
});
|
||||
sockChat.watch('user:clear', () => {
|
||||
if(dumpEvents) console.log('user:clear');
|
||||
sockChat.watch('user:clear', ev => {
|
||||
if(dumpEvents) console.log('user:clear', ev);
|
||||
|
||||
const self = Umi.User.currentUser;
|
||||
Umi.Users.Clear();
|
||||
|
@ -760,48 +788,48 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
Umi.Users.Add(self);
|
||||
});
|
||||
|
||||
sockChat.watch('chan:add', add => {
|
||||
if(dumpEvents) console.log('chan:add', add);
|
||||
sockChat.watch('chan:add', ev => {
|
||||
if(dumpEvents) console.log('chan:add', ev);
|
||||
|
||||
Umi.Channels.Add(new Umi.Channel(
|
||||
add.channel.name,
|
||||
add.channel.hasPassword,
|
||||
add.channel.isTemporary,
|
||||
ev.detail.channel.name,
|
||||
ev.detail.channel.hasPassword,
|
||||
ev.detail.channel.isTemporary,
|
||||
));
|
||||
});
|
||||
sockChat.watch('chan:remove', remove => {
|
||||
if(dumpEvents) console.log('chan:remove', remove);
|
||||
sockChat.watch('chan:remove', ev => {
|
||||
if(dumpEvents) console.log('chan:remove', ev);
|
||||
|
||||
Umi.Channels.Remove(Umi.Channels.Get(remove.channel.name));
|
||||
Umi.Channels.Remove(Umi.Channels.Get(ev.detail.channel.name));
|
||||
});
|
||||
sockChat.watch('chan:update', update => {
|
||||
if(dumpEvents) console.log('chan:update', update);
|
||||
sockChat.watch('chan:update', ev => {
|
||||
if(dumpEvents) console.log('chan:update', ev);
|
||||
|
||||
const chanInfo = Umi.Channels.Get(update.channel.previousName);
|
||||
chanInfo.setName(update.channel.name);
|
||||
chanInfo.setHasPassword(update.channel.hasPassword);
|
||||
chanInfo.setTemporary(update.channel.isTemporary);
|
||||
Umi.Channels.Update(update.channel.previousName, chanInfo);
|
||||
const chanInfo = Umi.Channels.Get(ev.detail.channel.previousName);
|
||||
chanInfo.setName(ev.detail.channel.name);
|
||||
chanInfo.setHasPassword(ev.detail.channel.hasPassword);
|
||||
chanInfo.setTemporary(ev.detail.channel.isTemporary);
|
||||
Umi.Channels.Update(ev.detail.channel.previousName, chanInfo);
|
||||
});
|
||||
sockChat.watch('chan:clear', () => {
|
||||
if(dumpEvents) console.log('chan:clear');
|
||||
sockChat.watch('chan:clear', ev => {
|
||||
if(dumpEvents) console.log('chan:clear', ev);
|
||||
|
||||
Umi.Channels.Clear();
|
||||
});
|
||||
sockChat.watch('chan:focus', focus => {
|
||||
if(dumpEvents) console.log('chan:focus', focus);
|
||||
sockChat.watch('chan:focus', ev => {
|
||||
if(dumpEvents) console.log('chan:focus', ev);
|
||||
|
||||
Umi.Channels.Switch(Umi.Channels.Get(focus.channel.name));
|
||||
Umi.Channels.Switch(Umi.Channels.Get(ev.detail.channel.name));
|
||||
});
|
||||
sockChat.watch('chan:join', join => {
|
||||
if(dumpEvents) console.log('chan:join', join);
|
||||
sockChat.watch('chan:join', ev => {
|
||||
if(dumpEvents) console.log('chan:join', ev);
|
||||
|
||||
const userInfo = new Umi.User(join.user.id, join.user.name, join.user.colour, join.user.permsRaw);
|
||||
const userInfo = new Umi.User(ev.detail.user.id, ev.detail.user.name, ev.detail.user.colour, ev.detail.user.permsRaw);
|
||||
Umi.Users.Add(userInfo);
|
||||
|
||||
if(join.msg !== undefined)
|
||||
if(ev.detail.msg !== undefined)
|
||||
Umi.Messages.Add(new Umi.Message(
|
||||
join.msg.id, null, undefined, '', join.msg.channel, false,
|
||||
ev.detail.msg.id, null, undefined, '', ev.detail.msg.channel, false,
|
||||
{
|
||||
isError: false,
|
||||
type: leave.msg.botInfo.type,
|
||||
|
@ -810,22 +838,22 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
},
|
||||
));
|
||||
});
|
||||
sockChat.watch('chan:leave', leave => {
|
||||
if(dumpEvents) console.log('chan:leave', leave);
|
||||
sockChat.watch('chan:leave', ev => {
|
||||
if(dumpEvents) console.log('chan:leave', ev);
|
||||
|
||||
if(leave.user.self)
|
||||
if(ev.detail.user.self)
|
||||
return;
|
||||
|
||||
const userInfo = Umi.Users.Get(leave.user.id);
|
||||
const userInfo = Umi.Users.Get(ev.detail.user.id);
|
||||
if(userInfo === null)
|
||||
return;
|
||||
|
||||
if(leave.msg !== undefined)
|
||||
if(ev.detail.msg !== undefined)
|
||||
Umi.Messages.Add(new Umi.Message(
|
||||
leave.msg.id, null, undefined, '', leave.msg.channel, false,
|
||||
ev.detail.msg.id, null, undefined, '', ev.detail.msg.channel, false,
|
||||
{
|
||||
isError: false,
|
||||
type: leave.msg.botInfo.type,
|
||||
type: ev.detail.msg.botInfo.type,
|
||||
args: [ userInfo.getName() ],
|
||||
target: userInfo,
|
||||
},
|
||||
|
@ -834,16 +862,16 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
Umi.Users.Remove(userInfo);
|
||||
});
|
||||
|
||||
sockChat.watch('msg:add', add => {
|
||||
if(dumpEvents) console.log('msg:add', add);
|
||||
sockChat.watch('msg:add', ev => {
|
||||
if(dumpEvents) console.log('msg:add', ev);
|
||||
|
||||
const senderInfo = add.msg.sender;
|
||||
const senderInfo = ev.detail.msg.sender;
|
||||
const userInfo = senderInfo.name === undefined
|
||||
? Umi.Users.Get(senderInfo.id)
|
||||
: new Umi.User(senderInfo.id, senderInfo.name, senderInfo.colour, senderInfo.permsRaw);
|
||||
|
||||
// hack
|
||||
let channelName = add.msg.channel;
|
||||
let channelName = ev.detail.msg.channel;
|
||||
if(channelName !== undefined && channelName.startsWith('@~')) {
|
||||
const chanUserInfo = Umi.Users.Get(channelName.substring(2));
|
||||
if(chanUserInfo !== null)
|
||||
|
@ -851,7 +879,7 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
}
|
||||
|
||||
// also hack
|
||||
if(add.msg.flags.isPM) {
|
||||
if(ev.detail.msg.flags.isPM) {
|
||||
if(Umi.Channels.Get(channelName) === null)
|
||||
Umi.Channels.Add(new Umi.Channel(channelName, false, true, true));
|
||||
|
||||
|
@ -860,29 +888,50 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
|||
}
|
||||
|
||||
Umi.Messages.Add(new Umi.Message(
|
||||
add.msg.id,
|
||||
add.msg.time,
|
||||
ev.detail.msg.id,
|
||||
ev.detail.msg.time,
|
||||
userInfo,
|
||||
add.msg.text,
|
||||
ev.detail.msg.text,
|
||||
channelName,
|
||||
false,
|
||||
add.msg.botInfo,
|
||||
add.msg.flags.isAction,
|
||||
add.msg.silent,
|
||||
ev.detail.msg.botInfo,
|
||||
ev.detail.msg.flags.isAction,
|
||||
ev.detail.msg.silent,
|
||||
));
|
||||
});
|
||||
sockChat.watch('msg:remove', remove => {
|
||||
if(dumpEvents) console.log('msg:remove', remove);
|
||||
sockChat.watch('msg:remove', ev => {
|
||||
if(dumpEvents) console.log('msg:remove', ev);
|
||||
|
||||
Umi.Messages.Remove(Umi.Messages.Get(remove.msg.id));
|
||||
Umi.Messages.Remove(Umi.Messages.Get(ev.detail.msg.id));
|
||||
});
|
||||
sockChat.watch('msg:clear', () => {
|
||||
if(dumpEvents) console.log('msg:clear');
|
||||
sockChat.watch('msg:clear', ev => {
|
||||
if(dumpEvents) console.log('msg:clear', ev);
|
||||
|
||||
Umi.UI.Messages.RemoveAll();
|
||||
});
|
||||
|
||||
sockChat.open();
|
||||
const conManAttempt = ev => {
|
||||
let message = ev.detail.attempt > 2 ? `Attempt ${ev.detail.attempt}...` : 'Connecting to server...';
|
||||
getLoadingOverlay('spinner', 'Connecting...', message);
|
||||
};
|
||||
const conManFail = ev => {
|
||||
getLoadingOverlay('cross', 'Failed to connect', `Retrying in ${ev.detail.delay / 1000} seconds...`);
|
||||
};
|
||||
|
||||
conMan.watch('attempt', conManAttempt);
|
||||
conMan.watch('fail', conManFail);
|
||||
|
||||
await conMan.start(async url => {
|
||||
await sockChat.open(url);
|
||||
});
|
||||
|
||||
conMan.unwatch('attempt', conManAttempt);
|
||||
conMan.unwatch('fail', conManFail);
|
||||
|
||||
getLoadingOverlay('spinner', 'Connecting...', 'Authenticating...');
|
||||
|
||||
const authInfo = MamiMisuzuAuth.getInfo();
|
||||
sockChat.sendAuth(authInfo.method, authInfo.token);
|
||||
|
||||
if(window.dispatchEvent)
|
||||
window.dispatchEvent(new Event('umi:connect'));
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
#include common.js
|
||||
#include utility.js
|
||||
|
||||
const UmiServers = (function() {
|
||||
let servers = undefined,
|
||||
index = Number.MAX_SAFE_INTEGER - 1;
|
||||
|
||||
return {
|
||||
getServer: function(callback) {
|
||||
// FutamiCommon is delayed load
|
||||
if(servers === undefined) {
|
||||
const futamiServers = futami.get('servers');
|
||||
$as(futamiServers);
|
||||
servers = futamiServers;
|
||||
}
|
||||
|
||||
if(++index >= servers.length)
|
||||
index = 0;
|
||||
|
||||
let server = servers[index];
|
||||
if(server.includes('//'))
|
||||
server = location.protocol.replace('http', 'ws') + server;
|
||||
|
||||
callback(server);
|
||||
},
|
||||
};
|
||||
})();
|
|
@ -1,4 +1,4 @@
|
|||
#include watcher.js
|
||||
#include eventtarget.js
|
||||
#include settings/scoped.js
|
||||
#include settings/virtual.js
|
||||
#include settings/webstorage.js
|
||||
|
@ -15,9 +15,16 @@ const MamiSettings = function(storageOrPrefix) {
|
|||
throw 'required methods do not exist in storageOrPrefix object';
|
||||
|
||||
const storage = new MamiSettingsVirtualStorage(storageOrPrefix);
|
||||
const watchers = new MamiWatchers;
|
||||
const settings = new Map;
|
||||
|
||||
const eventTarget = new MamiEventTarget('mami:setting');
|
||||
const createUpdateEvent = (name, value, initial) => eventTarget.create(name, {
|
||||
name: name,
|
||||
value: value,
|
||||
initial: !!initial,
|
||||
});
|
||||
const dispatchUpdate = (name, value) => eventTarget.dispatchEvent(createUpdateEvent(name, value));
|
||||
|
||||
const broadcast = new BroadcastChannel(`${MAMI_JS}:settings:${storage.name()}`);
|
||||
const broadcastUpdate = (name, value) => {
|
||||
setTimeout(() => broadcast.postMessage({ act: 'update', name: name, value: value }), 0);
|
||||
|
@ -43,7 +50,7 @@ const MamiSettings = function(storageOrPrefix) {
|
|||
return;
|
||||
|
||||
storage.delete(setting.name);
|
||||
watchers.call(setting.name, setting.fallback, setting.name);
|
||||
dispatchUpdate(setting.name, setting.fallback);
|
||||
broadcastUpdate(setting.name, setting.fallback);
|
||||
};
|
||||
|
||||
|
@ -89,7 +96,7 @@ const MamiSettings = function(storageOrPrefix) {
|
|||
} else
|
||||
storage.set(setting.name, value);
|
||||
|
||||
watchers.call(setting.name, value, setting.name);
|
||||
dispatchUpdate(setting.name, value);
|
||||
broadcastUpdate(setting.name, value);
|
||||
};
|
||||
|
||||
|
@ -98,7 +105,7 @@ const MamiSettings = function(storageOrPrefix) {
|
|||
return;
|
||||
|
||||
if(ev.data.act === 'update' && typeof ev.data.name === 'string') {
|
||||
watchers.call(ev.data.name, ev.data.value, ev.data.name);
|
||||
dispatchUpdate(ev.data.name, ev.data.value);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
@ -122,8 +129,6 @@ const MamiSettings = function(storageOrPrefix) {
|
|||
|
||||
if(virtual === true)
|
||||
storage.virtualise(name);
|
||||
|
||||
watchers.define(name);
|
||||
},
|
||||
info: name => getSetting(name),
|
||||
names: () => Array.from(settings.keys()),
|
||||
|
@ -143,7 +148,7 @@ const MamiSettings = function(storageOrPrefix) {
|
|||
},
|
||||
touch: name => {
|
||||
const setting = getSetting(name);
|
||||
watchers.call(setting.name, getValue(setting), setting.name);
|
||||
dispatchUpdate(setting.name, getValue(setting));
|
||||
},
|
||||
clear: (criticalOnly, prefix) => {
|
||||
for(const setting of settings.values())
|
||||
|
@ -152,10 +157,11 @@ const MamiSettings = function(storageOrPrefix) {
|
|||
},
|
||||
watch: (name, handler) => {
|
||||
const setting = getSetting(name);
|
||||
watchers.watch(setting.name, handler, getValue(setting), setting.name);
|
||||
eventTarget.watch(setting.name, handler);
|
||||
handler(createUpdateEvent(setting.name, getValue(setting), true));
|
||||
},
|
||||
unwatch: (name, handler) => {
|
||||
watchers.unwatch(getSetting(name).name, handler);
|
||||
eventTarget.unwatch(name, handler);
|
||||
},
|
||||
virtualise: name => storage.virtualise(getSetting(name).name),
|
||||
scope: name => new MamiSettingsScoped(pub, name),
|
||||
|
|
|
@ -1,18 +1,11 @@
|
|||
#include common.js
|
||||
#include servers.js
|
||||
#include watcher.js
|
||||
#include eventtarget.js
|
||||
#include websock.js
|
||||
|
||||
Umi.Protocol.SockChat.Protocol = function() {
|
||||
const watchers = new MamiWatchers(false);
|
||||
watchers.define([
|
||||
'conn:init', 'conn:ready', 'conn:lost', 'conn:error',
|
||||
'ping:send', 'ping:long', 'ping:recv',
|
||||
'session:start', 'session:fail', 'session:term',
|
||||
'user:add', 'user:remove', 'user:update', 'user:clear',
|
||||
'chan:add', 'chan:remove', 'chan:update', 'chan:clear', 'chan:focus', 'chan:join', 'chan:leave',
|
||||
'msg:add', 'msg:remove', 'msg:clear',
|
||||
]);
|
||||
Umi.Protocol.SockChat.Protocol = function(pingDuration) {
|
||||
if(typeof pingDuration !== 'number')
|
||||
throw 'pingDuration must be a number';
|
||||
|
||||
const eventTarget = new MamiEventTarget('mami:proto');
|
||||
|
||||
const parseUserColour = str => {
|
||||
// todo
|
||||
|
@ -37,8 +30,6 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
};
|
||||
|
||||
let wasConnected = false;
|
||||
let noReconnect = false;
|
||||
let connectAttempts = 0;
|
||||
let wasKicked = false;
|
||||
let isRestarting = false;
|
||||
let dumpPackets = false;
|
||||
|
@ -46,6 +37,7 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
let sock;
|
||||
let selfUserId, selfChannelName, selfPseudoChannelName;
|
||||
let lastPing, lastPong, pingTimer, pingWatcher;
|
||||
let openResolve, openReject;
|
||||
|
||||
const handlers = {};
|
||||
|
||||
|
@ -61,7 +53,7 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
stopPingWatcher();
|
||||
|
||||
if(lastPong === undefined)
|
||||
watchers.call('ping:long');
|
||||
eventTarget.dispatch('ping:long');
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
|
@ -81,7 +73,7 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
if(selfUserId === undefined)
|
||||
return;
|
||||
|
||||
watchers.call('ping:send');
|
||||
eventTarget.dispatch('ping:send');
|
||||
startPingWatcher();
|
||||
|
||||
lastPong = undefined;
|
||||
|
@ -101,7 +93,7 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
send('2', selfUserId, text);
|
||||
};
|
||||
|
||||
const startKeepAlive = () => sock?.sendInterval(`0\t${selfUserId}`, futami.get('ping') * 1000);
|
||||
const startKeepAlive = () => sock?.sendInterval(`0\t${selfUserId}`, pingDuration);
|
||||
const stopKeepAlive = () => sock?.clearIntervals();
|
||||
|
||||
const onOpen = ev => {
|
||||
|
@ -110,11 +102,10 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
|
||||
isRestarting = false;
|
||||
|
||||
// see if these are neccesary
|
||||
watchers.call('user:clear');
|
||||
watchers.call('chan:clear');
|
||||
|
||||
watchers.call('conn:ready', { wasConnected: wasConnected });
|
||||
if(typeof openResolve === 'function') {
|
||||
openResolve();
|
||||
openResolve = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
const onClose = ev => {
|
||||
|
@ -130,36 +121,32 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
if(wasKicked)
|
||||
return;
|
||||
|
||||
let code = ev.code;
|
||||
let code = ev.detail.code;
|
||||
if(isRestarting && code === 1006) {
|
||||
code = 1012;
|
||||
} else if(code === 1012)
|
||||
isRestarting = true;
|
||||
|
||||
watchers.call('conn:lost', {
|
||||
if(typeof openReject === 'function') {
|
||||
openReject({
|
||||
code: code,
|
||||
wasConnected: wasConnected,
|
||||
isRestarting: isRestarting,
|
||||
});
|
||||
openReject = undefined;
|
||||
}
|
||||
|
||||
eventTarget.dispatch('conn:lost', {
|
||||
wasConnected: wasConnected,
|
||||
isRestarting: isRestarting,
|
||||
code: code,
|
||||
});
|
||||
|
||||
connectAttempts = 0;
|
||||
|
||||
setTimeout(() => beginConnecting(), 5000);
|
||||
};
|
||||
|
||||
const onError = ex => {
|
||||
watchers.call('conn:error', ex);
|
||||
};
|
||||
|
||||
const unfuckText = text => {
|
||||
const elem = document.createElement('div');
|
||||
elem.innerHTML = text.replace(/ <br\/> /g, "\n");
|
||||
text = elem.innerText;
|
||||
return text;
|
||||
};
|
||||
const unfuckText = text => text.replace(/ <br\/> /g, "\n");
|
||||
|
||||
const onMessage = ev => {
|
||||
const args = ev.data.split("\t");
|
||||
const args = ev.detail.data.split("\t");
|
||||
let handler = handlers;
|
||||
|
||||
if(dumpPackets)
|
||||
|
@ -181,7 +168,7 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
// pong handler
|
||||
handlers['0'] = () => {
|
||||
lastPong = Date.now();
|
||||
watchers.call('ping:recv', {
|
||||
eventTarget.dispatch('ping:recv', {
|
||||
ping: lastPing,
|
||||
pong: lastPong,
|
||||
diff: lastPong - lastPing,
|
||||
|
@ -194,7 +181,7 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
selfUserId = userIdOrReason;
|
||||
selfChannelName = chanNameOrMsgId;
|
||||
|
||||
watchers.call('session:start', {
|
||||
eventTarget.dispatch('session:start', {
|
||||
wasConnected: wasConnected,
|
||||
session: { success: true },
|
||||
ctx: {
|
||||
|
@ -235,11 +222,11 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
until: userNameOrExpiry === '-1' ? undefined : new Date(parseInt(userNameOrExpiry) * 1000),
|
||||
};
|
||||
|
||||
watchers.call('session:fail', failInfo);
|
||||
eventTarget.dispatch('session:fail', failInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
watchers.call('user:add', {
|
||||
eventTarget.dispatch('user:add', {
|
||||
msg: {
|
||||
id: chanNameOrMsgId,
|
||||
time: new Date(parseInt(successOrTimeStamp) * 1000),
|
||||
|
@ -300,12 +287,12 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
};
|
||||
}
|
||||
|
||||
watchers.call('msg:add', msgInfo);
|
||||
eventTarget.dispatch('msg:add', msgInfo);
|
||||
};
|
||||
|
||||
// user leave
|
||||
handlers['3'] = (userId, userName, reason, timeStamp, msgId) => {
|
||||
watchers.call('user:remove', {
|
||||
eventTarget.dispatch('user:remove', {
|
||||
leave: { type: reason },
|
||||
msg: {
|
||||
id: msgId,
|
||||
|
@ -329,7 +316,7 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
|
||||
// channel add
|
||||
handlers['4']['0'] = (name, hasPass, isTemp) => {
|
||||
watchers.call('chan:add', {
|
||||
eventTarget.dispatch('chan:add', {
|
||||
channel: {
|
||||
name: name,
|
||||
hasPassword: hasPass !== '0',
|
||||
|
@ -340,7 +327,7 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
|
||||
// channel update
|
||||
handlers['4']['1'] = (prevName, name, hasPass, isTemp) => {
|
||||
watchers.call('chan:update', {
|
||||
eventTarget.dispatch('chan:update', {
|
||||
channel: {
|
||||
previousName: prevName,
|
||||
name: name,
|
||||
|
@ -352,7 +339,7 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
|
||||
// channel remove
|
||||
handlers['4']['2'] = name => {
|
||||
watchers.call('chan:remove', {
|
||||
eventTarget.dispatch('chan:remove', {
|
||||
channel: { name: name },
|
||||
});
|
||||
};
|
||||
|
@ -362,7 +349,7 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
|
||||
// user join channel
|
||||
handlers['5']['0'] = (userId, userName, userColour, userPerms, msgId) => {
|
||||
watchers.call('chan:join', {
|
||||
eventTarget.dispatch('chan:join', {
|
||||
user: {
|
||||
id: userId,
|
||||
self: userId === selfUserId,
|
||||
|
@ -384,7 +371,7 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
|
||||
// user leave channel
|
||||
handlers['5']['1'] = (userId, msgId) => {
|
||||
watchers.call('chan:leave', {
|
||||
eventTarget.dispatch('chan:leave', {
|
||||
user: {
|
||||
id: userId,
|
||||
self: userId === selfUserId,
|
||||
|
@ -404,14 +391,14 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
handlers['5']['2'] = name => {
|
||||
selfChannelName = name;
|
||||
|
||||
watchers.call('chan:focus', {
|
||||
eventTarget.dispatch('chan:focus', {
|
||||
channel: { name: selfChannelName },
|
||||
});
|
||||
};
|
||||
|
||||
// message delete
|
||||
handlers['6'] = msgId => {
|
||||
watchers.call('msg:remove', {
|
||||
eventTarget.dispatch('msg:remove', {
|
||||
msg: {
|
||||
id: msgId,
|
||||
channel: selfChannelName,
|
||||
|
@ -425,11 +412,12 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
// existing users
|
||||
handlers['7']['0'] = (count, ...args) => {
|
||||
count = parseInt(count);
|
||||
eventTarget.dispatch('user:clear');
|
||||
|
||||
for(let i = 0; i < count; ++i) {
|
||||
const offset = 5 * i;
|
||||
|
||||
watchers.call('user:add', {
|
||||
eventTarget.dispatch('user:add', {
|
||||
user: {
|
||||
id: args[offset],
|
||||
self: args[offset] === selfUserId,
|
||||
|
@ -479,17 +467,18 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
};
|
||||
}
|
||||
|
||||
watchers.call('msg:add', info);
|
||||
eventTarget.dispatch('msg:add', info);
|
||||
};
|
||||
|
||||
// existing channels
|
||||
handlers['7']['2'] = (count, ...args) => {
|
||||
count = parseInt(count);
|
||||
eventTarget.dispatch('chan:clear');
|
||||
|
||||
for(let i = 0; i < count; ++i) {
|
||||
const offset = 3 * i;
|
||||
|
||||
watchers.call('chan:add', {
|
||||
eventTarget.dispatch('chan:add', {
|
||||
channel: {
|
||||
name: args[offset],
|
||||
hasPassword: args[offset + 1] !== '0',
|
||||
|
@ -499,7 +488,7 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
});
|
||||
}
|
||||
|
||||
watchers.call('chan:focus', {
|
||||
eventTarget.dispatch('chan:focus', {
|
||||
channel: { name: selfChannelName },
|
||||
});
|
||||
};
|
||||
|
@ -507,18 +496,17 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
// context clear
|
||||
handlers['8'] = mode => {
|
||||
if(mode === '0' || mode === '3' || mode === '4')
|
||||
watchers.call('msg:clear');
|
||||
eventTarget.dispatch('msg:clear');
|
||||
|
||||
if(mode === '1' || mode === '3' || mode === '4')
|
||||
watchers.call('user:clear');
|
||||
eventTarget.dispatch('user:clear');
|
||||
|
||||
if(mode === '2' || mode === '4')
|
||||
watchers.call('chan:clear');
|
||||
eventTarget.dispatch('chan:clear');
|
||||
};
|
||||
|
||||
// baka (ban/kick)
|
||||
handlers['9'] = (type, expiry) => {
|
||||
noReconnect = true;
|
||||
wasKicked = true;
|
||||
|
||||
const bakaInfo = {
|
||||
|
@ -533,12 +521,12 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
bakaInfo.baka.until = expiry === '-1' ? undefined : new Date(parseInt(expiry) * 1000);
|
||||
}
|
||||
|
||||
watchers.call('session:term', bakaInfo);
|
||||
eventTarget.dispatch('session:term', bakaInfo);
|
||||
};
|
||||
|
||||
// user update
|
||||
handlers['10'] = (userId, userName, userColour, userPerms) => {
|
||||
watchers.call('user:update', {
|
||||
eventTarget.dispatch('user:update', {
|
||||
user: {
|
||||
id: userId,
|
||||
self: userId === selfUserId,
|
||||
|
@ -551,61 +539,43 @@ Umi.Protocol.SockChat.Protocol = function() {
|
|||
};
|
||||
|
||||
|
||||
const beginConnecting = () => {
|
||||
sock?.close();
|
||||
|
||||
if(noReconnect)
|
||||
return;
|
||||
|
||||
UmiServers.getServer(server => {
|
||||
watchers.call('conn:init', {
|
||||
server: server,
|
||||
wasConnected: wasConnected,
|
||||
attempt: ++connectAttempts,
|
||||
});
|
||||
|
||||
sock = new UmiWebSocket(server, ev => {
|
||||
switch(ev.act) {
|
||||
case 'ws:open':
|
||||
onOpen(ev);
|
||||
break;
|
||||
case 'ws:close':
|
||||
onClose(ev);
|
||||
break;
|
||||
case 'ws:message':
|
||||
onMessage(ev);
|
||||
break;
|
||||
case 'ws:create_interval':
|
||||
pingTimer = ev.id;
|
||||
break;
|
||||
case 'ws:call_interval':
|
||||
if(ev.id === pingTimer)
|
||||
onSendPing();
|
||||
break;
|
||||
case 'ws:clear_intervals':
|
||||
pingTimer = undefined;
|
||||
break;
|
||||
default:
|
||||
console.log(ev.data);
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
sendAuth: sendAuth,
|
||||
sendMessage: sendMessage,
|
||||
open: () => {
|
||||
noReconnect = false;
|
||||
beginConnecting();
|
||||
open: url => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if(typeof url !== 'string')
|
||||
throw 'url must be a string';
|
||||
if(url.startsWith('//'))
|
||||
url = location.protocol.replace('http', 'ws') + url;
|
||||
|
||||
openResolve = resolve;
|
||||
openReject = reject;
|
||||
|
||||
sock?.close();
|
||||
|
||||
sock = new UmiWebSocket(url);
|
||||
sock.watch('open', onOpen);
|
||||
sock.watch('close', onClose);
|
||||
sock.watch('message', onMessage);
|
||||
sock.watch('create_interval', ev => {
|
||||
pingTimer = ev.detail.id;
|
||||
});
|
||||
sock.watch('call_interval', ev => {
|
||||
if(ev.detail.id === pingTimer)
|
||||
onSendPing();
|
||||
});
|
||||
sock.watch('create_intervals', ev => {
|
||||
pingTimer = undefined;
|
||||
});
|
||||
});
|
||||
},
|
||||
close: () => {
|
||||
noReconnect = true;
|
||||
sock?.close();
|
||||
sock = undefined;
|
||||
},
|
||||
watch: (name, handler) => watchers.watch(name, handler),
|
||||
unwatch: (name, handler) => watchers.unwatch(name, handler),
|
||||
watch: eventTarget.watch,
|
||||
unwatch: eventTarget.unwatch,
|
||||
setDumpPackets: state => dumpPackets = !!state,
|
||||
switchChannel: channelInfo => {
|
||||
if(selfUserId === undefined)
|
||||
|
|
|
@ -31,7 +31,7 @@ Umi.UI.LoadingOverlay = function(icon, header, message) {
|
|||
};
|
||||
|
||||
const setHeader = text => headerElem.textContent = (text || '').toString();
|
||||
const setMessage = text => messageElem.textContent = (text || '').toString();
|
||||
const setMessage = text => messageElem.innerHTML = (text || '').toString();
|
||||
|
||||
setIcon(icon);
|
||||
setHeader(header);
|
||||
|
@ -44,8 +44,5 @@ Umi.UI.LoadingOverlay = function(icon, header, message) {
|
|||
getElement: function() {
|
||||
return html;
|
||||
},
|
||||
implode: function() {
|
||||
html.parentNode.removeChild(html);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
@ -13,15 +13,41 @@ const MamiPingIndicator = function(initialStrength) {
|
|||
for(let i = 1; i <= 3; ++i)
|
||||
bars.push(html.appendChild(<div class={`ping-bar ping-bar-${i}`}/>));
|
||||
|
||||
let interval;
|
||||
|
||||
const setStrength = strength => {
|
||||
if(typeof strength !== 'number')
|
||||
throw 'strength must be a number';
|
||||
|
||||
for(const i in bars)
|
||||
bars[i].classList.toggle('ping-bar-on', i < strength);
|
||||
if(strength < 0) {
|
||||
if(interval === undefined) {
|
||||
const cyclesMax = bars.length * 2;
|
||||
let cycles = -1;
|
||||
|
||||
const updateCycle = () => {
|
||||
let curCycle = ++cycles % cyclesMax;
|
||||
if(curCycle > bars.length)
|
||||
curCycle = cyclesMax - curCycle;
|
||||
|
||||
for(const i in bars)
|
||||
bars[i].classList.toggle('ping-bar-on', curCycle === (parseInt(i) + 1));
|
||||
};
|
||||
|
||||
interval = setInterval(updateCycle, 200);
|
||||
updateCycle();
|
||||
}
|
||||
} else {
|
||||
if(interval !== undefined) {
|
||||
clearInterval(interval);
|
||||
interval = undefined;
|
||||
}
|
||||
|
||||
for(const i in bars)
|
||||
bars[i].classList.toggle('ping-bar-on', i < strength);
|
||||
}
|
||||
|
||||
html.classList.toggle('ping-state-good', strength > 1);
|
||||
html.classList.toggle('ping-state-warn', strength === 1);
|
||||
html.classList.toggle('ping-state-warn', strength == 1);
|
||||
html.classList.toggle('ping-state-poor', strength < 1);
|
||||
};
|
||||
|
||||
|
|
|
@ -454,7 +454,7 @@ Umi.UI.Settings = (function() {
|
|||
input.disabled = true;
|
||||
|
||||
if(display.type === 'checkbox') {
|
||||
mami.settings.watch(setting.name, v => input.checked = v);
|
||||
mami.settings.watch(setting.name, ev => input.checked = ev.detail.value);
|
||||
input.addEventListener('change', () => {
|
||||
if(display.confirm !== undefined && input.checked !== setting.fallback && !confirm(display.confirm)) {
|
||||
input.checked = setting.fallback;
|
||||
|
@ -464,7 +464,7 @@ Umi.UI.Settings = (function() {
|
|||
mami.settings.toggle(setting.name);
|
||||
});
|
||||
} else {
|
||||
mami.settings.watch(setting.name, v => input.value = v);
|
||||
mami.settings.watch(setting.name, ev => input.value = ev.detail.value);
|
||||
input.addEventListener('change', () => mami.settings.set(setting.name, input.value));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
#include utility.js
|
||||
|
||||
const MamiWatcher = function(initCall) {
|
||||
if(typeof initCall !== 'boolean')
|
||||
initCall = true;
|
||||
|
||||
const handlers = [];
|
||||
|
||||
const watch = (handler, ...args) => {
|
||||
if(typeof handler !== 'function')
|
||||
throw 'handler must be a function';
|
||||
if(handlers.includes(handler))
|
||||
throw 'handler already registered';
|
||||
|
||||
handlers.push(handler);
|
||||
|
||||
if(initCall) {
|
||||
args.push(true);
|
||||
handler(...args);
|
||||
}
|
||||
};
|
||||
|
||||
const unwatch = handler => {
|
||||
$ari(handlers, handler);
|
||||
};
|
||||
|
||||
return {
|
||||
watch: watch,
|
||||
unwatch: unwatch,
|
||||
call: (...args) => {
|
||||
if(initCall)
|
||||
args.push(false);
|
||||
|
||||
for(const handler of handlers)
|
||||
handler(...args);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const MamiWatchers = function(initCall) {
|
||||
if(typeof initCall !== 'boolean')
|
||||
initCall = true;
|
||||
|
||||
const watchers = new Map;
|
||||
|
||||
const getWatcher = name => {
|
||||
const watcher = watchers.get(name);
|
||||
if(watcher === undefined)
|
||||
throw 'undefined watcher name';
|
||||
return watcher;
|
||||
};
|
||||
|
||||
const watch = (name, handler, ...args) => {
|
||||
getWatcher(name).watch(handler, ...args);
|
||||
};
|
||||
|
||||
const unwatch = (name, handler) => {
|
||||
getWatcher(name).unwatch(handler);
|
||||
};
|
||||
|
||||
return {
|
||||
watch: watch,
|
||||
unwatch: unwatch,
|
||||
define: names => {
|
||||
if(typeof names === 'string')
|
||||
watchers.set(names, new MamiWatcher(initCall));
|
||||
else if(Array.isArray(names))
|
||||
for(const name of names)
|
||||
watchers.set(name, new MamiWatcher(initCall));
|
||||
else
|
||||
throw 'names must be an array of names or a single name';
|
||||
},
|
||||
call: (name, ...args) => {
|
||||
getWatcher(name).call(...args);
|
||||
},
|
||||
};
|
||||
};
|
|
@ -1,6 +1,8 @@
|
|||
const UmiWebSocket = function(server, message, useWorker) {
|
||||
if(typeof useWorker === 'undefined')
|
||||
useWorker = (function() {
|
||||
#include eventtarget.js
|
||||
|
||||
const UmiWebSocket = function(url, useWorker) {
|
||||
if(typeof useWorker !== 'boolean')
|
||||
useWorker = (() => {
|
||||
// Overrides
|
||||
if(mami.settings.get('neverUseWorker'))
|
||||
return false;
|
||||
|
@ -18,90 +20,68 @@ const UmiWebSocket = function(server, message, useWorker) {
|
|||
return false;
|
||||
})();
|
||||
|
||||
const eventTarget = new MamiEventTarget('ws');
|
||||
let send, close, sendInterval, clearIntervals;
|
||||
|
||||
if(useWorker) {
|
||||
const worker = new Worker(MAMI_WS);
|
||||
worker.addEventListener('message', function(ev) {
|
||||
message(ev.data);
|
||||
worker.addEventListener('message', ev => {
|
||||
if(ev.data.act.startsWith('ws:'))
|
||||
eventTarget.dispatch(ev.data.act.substring(3), ev.data.detail);
|
||||
});
|
||||
worker.postMessage({act: 'ws:open', server: server});
|
||||
send = function(text) {
|
||||
worker.postMessage({act: 'ws:open', url: url});
|
||||
send = text => {
|
||||
worker.postMessage({act: 'ws:send', text: text});
|
||||
};
|
||||
close = function() {
|
||||
close = () => {
|
||||
worker.postMessage({act: 'ws:close'});
|
||||
};
|
||||
getIntervals = function() {
|
||||
worker.postMessage({act: 'ws:intervals'});
|
||||
};
|
||||
sendInterval = function(text, interval) {
|
||||
sendInterval = (text, interval) => {
|
||||
worker.postMessage({act: 'ws:send_interval', text: text, interval: interval});
|
||||
};
|
||||
clearIntervals = function() {
|
||||
clearIntervals = () => {
|
||||
worker.postMessage({act: 'ws:clear_intervals'});
|
||||
};
|
||||
} else {
|
||||
const websocket = new WebSocket(server), intervals = [];
|
||||
websocket.addEventListener('open', function(ev) {
|
||||
message({
|
||||
act: 'ws:open',
|
||||
type: ev.type,
|
||||
timeStamp: ev.timeStamp,
|
||||
isTrusted: ev.isTrusted,
|
||||
});
|
||||
const websocket = new WebSocket(url), intervals = [];
|
||||
websocket.addEventListener('open', ev => {
|
||||
eventTarget.dispatch('open');
|
||||
});
|
||||
websocket.addEventListener('close', function(ev) {
|
||||
message({
|
||||
act: 'ws:close',
|
||||
type: ev.type,
|
||||
timeStamp: ev.timeStamp,
|
||||
isTrusted: ev.isTrusted,
|
||||
websocket.addEventListener('close', ev => {
|
||||
eventTarget.dispatch('close', {
|
||||
code: ev.code,
|
||||
reason: ev.reason,
|
||||
wasClean: ev.wasClean,
|
||||
});
|
||||
});
|
||||
websocket.addEventListener('error', function(ev) {
|
||||
message({
|
||||
act: 'ws:error',
|
||||
type: ev.type,
|
||||
timeStamp: ev.timeStamp,
|
||||
isTrusted: ev.isTrusted,
|
||||
});
|
||||
websocket.addEventListener('error', ev => {
|
||||
eventTarget.dispatch('error');
|
||||
});
|
||||
websocket.addEventListener('message', function(ev) {
|
||||
message({
|
||||
act: 'ws:message',
|
||||
type: ev.type,
|
||||
timeStamp: ev.timeStamp,
|
||||
isTrusted: ev.isTrusted,
|
||||
websocket.addEventListener('message', ev => {
|
||||
eventTarget.dispatch('message', {
|
||||
data: ev.data,
|
||||
origin: ev.origin,
|
||||
lastEventId: ev.lastEventId,
|
||||
});
|
||||
});
|
||||
send = function(text) {
|
||||
send = text => {
|
||||
websocket.send(text);
|
||||
};
|
||||
close = function() {
|
||||
close = () => {
|
||||
websocket.close();
|
||||
};
|
||||
getIntervals = function() {
|
||||
return intervals;
|
||||
};
|
||||
sendInterval = function(text, interval) {
|
||||
const intervalId = setInterval(function() {
|
||||
sendInterval = (text, interval) => {
|
||||
const intervalId = setInterval(() => {
|
||||
if(websocket) {
|
||||
websocket.send(text);
|
||||
message({ act: 'ws:call_interval', id: intervalId });
|
||||
eventTarget.dispatch('call_interval', { id: intervalId });
|
||||
}
|
||||
}, interval);
|
||||
|
||||
intervals.push(intervalId);
|
||||
message({ act: 'ws:create_interval', id: intervalId });
|
||||
eventTarget.dispatch('create_interval', { id: intervalId });
|
||||
};
|
||||
clearIntervals = function() {
|
||||
clearIntervals = () => {
|
||||
for(let i = 0; i < intervals.length; ++i)
|
||||
clearInterval(intervals[i]);
|
||||
};
|
||||
|
@ -111,8 +91,9 @@ const UmiWebSocket = function(server, message, useWorker) {
|
|||
isUsingWorker: useWorker,
|
||||
send: send,
|
||||
close: close,
|
||||
getIntervals: getIntervals,
|
||||
sendInterval: sendInterval,
|
||||
clearIntervals: clearIntervals,
|
||||
watch: eventTarget.watch,
|
||||
unwatch: eventTarget.unwatch,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -6,46 +6,34 @@ addEventListener('message', function(ev) {
|
|||
|
||||
switch(ev.data.act) {
|
||||
case 'ws:open':
|
||||
if(!ev.data.server)
|
||||
if(!ev.data.url)
|
||||
break;
|
||||
|
||||
websocket = new WebSocket(ev.data.server);
|
||||
websocket = new WebSocket(ev.data.url);
|
||||
websocket.addEventListener('open', function(ev) {
|
||||
postMessage({
|
||||
act: 'ws:open',
|
||||
type: ev.type,
|
||||
timeStamp: ev.timeStamp,
|
||||
isTrusted: ev.isTrusted,
|
||||
});
|
||||
postMessage({ act: 'ws:open' });
|
||||
});
|
||||
websocket.addEventListener('close', function(ev) {
|
||||
postMessage({
|
||||
act: 'ws:close',
|
||||
type: ev.type,
|
||||
timeStamp: ev.timeStamp,
|
||||
isTrusted: ev.isTrusted,
|
||||
code: ev.code,
|
||||
reason: ev.reason,
|
||||
wasClean: ev.wasClean,
|
||||
detail: {
|
||||
code: ev.code,
|
||||
reason: ev.reason,
|
||||
wasClean: ev.wasClean,
|
||||
},
|
||||
});
|
||||
});
|
||||
websocket.addEventListener('error', function(ev) {
|
||||
postMessage({
|
||||
act: 'ws:error',
|
||||
type: ev.type,
|
||||
timeStamp: ev.timeStamp,
|
||||
isTrusted: ev.isTrusted,
|
||||
});
|
||||
postMessage({ act: 'ws:error' });
|
||||
});
|
||||
websocket.addEventListener('message', function(ev) {
|
||||
postMessage({
|
||||
act: 'ws:message',
|
||||
type: ev.type,
|
||||
timeStamp: ev.timeStamp,
|
||||
isTrusted: ev.isTrusted,
|
||||
data: ev.data,
|
||||
origin: ev.origin,
|
||||
lastEventId: ev.lastEventId,
|
||||
detail: {
|
||||
data: ev.data,
|
||||
origin: ev.origin,
|
||||
lastEventId: ev.lastEventId,
|
||||
},
|
||||
});
|
||||
});
|
||||
break;
|
||||
|
@ -66,24 +54,17 @@ addEventListener('message', function(ev) {
|
|||
websocket.send(ev.data.text);
|
||||
break;
|
||||
|
||||
case 'ws:intervals':
|
||||
postMessage({
|
||||
act: 'ws:intervals',
|
||||
intervals: intervals,
|
||||
});
|
||||
break;
|
||||
|
||||
case 'ws:send_interval':
|
||||
(function(interval, text) {
|
||||
const intervalId = setInterval(function() {
|
||||
if(websocket) {
|
||||
websocket.send(text);
|
||||
postMessage({ act: 'ws:call_interval', id: intervalId });
|
||||
postMessage({ act: 'ws:call_interval', detail: { id: intervalId } });
|
||||
}
|
||||
}, interval);
|
||||
|
||||
intervals.push(intervalId);
|
||||
postMessage({ act: 'ws:create_interval', id: intervalId });
|
||||
postMessage({ act: 'ws:create_interval', detail: { id: intervalId } });
|
||||
})(ev.data.interval, ev.data.text);
|
||||
break;
|
||||
|
||||
|
|
Loading…
Reference in a new issue