flash
cf71bab92d
This has been in the works for over a month and might break things because it's a very radical change. If it causes you to be unable to join chat, report it on the forum or try joining using the legacy chat on https://sockchat.flashii.net.
134 lines
3.6 KiB
JavaScript
134 lines
3.6 KiB
JavaScript
#include awaitable.js
|
|
#include utility.js
|
|
|
|
const MamiConnectionManager = function(client, settings, urls, eventTarget) {
|
|
const validateClient = value => {
|
|
if(typeof value !== 'object' || value === null)
|
|
throw 'client must be a non-null object';
|
|
};
|
|
|
|
validateClient(client);
|
|
|
|
if(typeof settings !== 'object' || settings === null)
|
|
throw 'settings must be a non-null object';
|
|
if(!Array.isArray(urls))
|
|
throw 'urls must be an array';
|
|
if(typeof eventTarget !== 'object' || eventTarget === null)
|
|
throw 'eventTarget must be a non-null object';
|
|
|
|
const delays = [
|
|
0,
|
|
2000, 2000, 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 startResolve;
|
|
|
|
const resetTimeout = () => {
|
|
if(timeout !== undefined) {
|
|
clearTimeout(timeout);
|
|
timeout = undefined;
|
|
}
|
|
};
|
|
|
|
const clear = () => {
|
|
resetTimeout();
|
|
attempts = started = delay = 0;
|
|
url = undefined;
|
|
};
|
|
|
|
$as(urls);
|
|
|
|
const attempt = () => {
|
|
started = Date.now();
|
|
url = urls[attempts % urls.length];
|
|
if(url.startsWith('//'))
|
|
url = location.protocol.replace('http', 'ws') + url;
|
|
|
|
const attemptNo = attempts + 1;
|
|
|
|
timeout = setTimeout(() => {
|
|
resetTimeout();
|
|
|
|
(async () => {
|
|
if(settings.get('onlyConnectWhenVisible'))
|
|
await MamiWaitVisible();
|
|
|
|
eventTarget.dispatch('attempt', {
|
|
url: url,
|
|
started: started,
|
|
attempt: attemptNo,
|
|
});
|
|
|
|
try {
|
|
const result = await client.connect(url);
|
|
if(typeof result === 'boolean' && !result)
|
|
throw {};
|
|
|
|
eventTarget.dispatch('success', {
|
|
url: url,
|
|
started: started,
|
|
attempt: attemptNo,
|
|
});
|
|
|
|
startResolve();
|
|
startResolve = undefined;
|
|
} catch(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();
|
|
}
|
|
})();
|
|
}, delay);
|
|
};
|
|
|
|
const isActive = () => timeout !== undefined || startResolve !== undefined;
|
|
|
|
return {
|
|
get isActive() { return isActive(); },
|
|
|
|
get client() { return client; },
|
|
set client(value) {
|
|
validateClient(value);
|
|
client = value;
|
|
},
|
|
|
|
start: () => {
|
|
return new Promise(resolve => {
|
|
if(isActive())
|
|
throw 'already attempting to connect';
|
|
|
|
startResolve = resolve;
|
|
|
|
clear();
|
|
attempt();
|
|
});
|
|
},
|
|
force: () => {
|
|
if(!isActive())
|
|
return;
|
|
|
|
resetTimeout();
|
|
delay = 0;
|
|
attempt();
|
|
},
|
|
clear: clear,
|
|
watch: eventTarget.watch,
|
|
unwatch: eventTarget.unwatch,
|
|
};
|
|
};
|