You want promises? I bring you commitments.
This commit is contained in:
parent
fcccccb6bc
commit
ab95a803b4
9 changed files with 379 additions and 276 deletions
68
src/ami.js/commitment.js
Normal file
68
src/ami.js/commitment.js
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
const Commitment = function(run) {
|
||||||
|
if(typeof run !== 'function')
|
||||||
|
throw 'run must be a function';
|
||||||
|
|
||||||
|
let success;
|
||||||
|
let fail = ex => { console.error(ex); };
|
||||||
|
let always;
|
||||||
|
|
||||||
|
const pub = {
|
||||||
|
success(handler) {
|
||||||
|
if(typeof handler !== 'function')
|
||||||
|
throw 'success handler must be a function';
|
||||||
|
|
||||||
|
success = handler;
|
||||||
|
return pub;
|
||||||
|
},
|
||||||
|
fail(handler) {
|
||||||
|
if(typeof handler !== 'function')
|
||||||
|
throw 'fail handler must be a function';
|
||||||
|
|
||||||
|
fail = handler;
|
||||||
|
return pub;
|
||||||
|
},
|
||||||
|
always(handler) {
|
||||||
|
if(typeof handler !== 'function')
|
||||||
|
throw 'always handler must be a function';
|
||||||
|
|
||||||
|
always = handler;
|
||||||
|
return pub;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const successHandler = (...args) => {
|
||||||
|
try {
|
||||||
|
if(typeof success === 'function')
|
||||||
|
success(...args);
|
||||||
|
} catch(ex) {
|
||||||
|
fail(ex);
|
||||||
|
} finally {
|
||||||
|
if(typeof always === 'function')
|
||||||
|
always();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const failHandler = (...args) => {
|
||||||
|
try {
|
||||||
|
fail(...args);
|
||||||
|
} catch(ex) {
|
||||||
|
fail(ex);
|
||||||
|
} finally {
|
||||||
|
if(typeof always === 'function')
|
||||||
|
always();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub.run = () => {
|
||||||
|
try {
|
||||||
|
run(successHandler, failHandler);
|
||||||
|
} catch(ex) {
|
||||||
|
fail(ex);
|
||||||
|
} finally {
|
||||||
|
if(typeof always === 'function')
|
||||||
|
always();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return Object.freeze(pub);
|
||||||
|
};
|
|
@ -1,3 +1,6 @@
|
||||||
|
#include commitment.js
|
||||||
|
#include xhr.js
|
||||||
|
|
||||||
var FutamiCommon = function(vars) {
|
var FutamiCommon = function(vars) {
|
||||||
vars = vars || {};
|
vars = vars || {};
|
||||||
|
|
||||||
|
@ -7,57 +10,41 @@ var FutamiCommon = function(vars) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
get: get,
|
get: get,
|
||||||
getJson: function(name, onload, onerror, noCache) {
|
getJson: function(name, noCache) {
|
||||||
if(typeof onload !== 'function')
|
return new Commitment((success, fail) => {
|
||||||
throw 'onload must be specified';
|
const options = { type: 'json' };
|
||||||
|
if(noCache)
|
||||||
|
options.headers = { 'Cache-Control': 'no-cache' };
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest;
|
$xhr.get(get(name), options)
|
||||||
xhr.onload = function() {
|
.success(({ body }) => { success(body); })
|
||||||
onload(JSON.parse(xhr.responseText));
|
.fail(fail)
|
||||||
};
|
.run();
|
||||||
if(typeof onerror === 'function')
|
});
|
||||||
xhr.onerror = function() { onerror(); };
|
|
||||||
xhr.open('GET', get(name));
|
|
||||||
if(noCache)
|
|
||||||
xhr.setRequestHeader('Cache-Control', 'no-cache');
|
|
||||||
xhr.send();
|
|
||||||
},
|
},
|
||||||
getApiJson: function(path, onload, onerror, noCache) {
|
getApiJson: function(path, noCache) {
|
||||||
if(typeof onload !== 'function')
|
return new Commitment((success, fail) => {
|
||||||
throw 'onload must be specified';
|
const options = { type: 'json' };
|
||||||
|
if(noCache)
|
||||||
|
options.headers = { 'Cache-Control': 'no-cache' };
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest;
|
$xhr.get(get('api') + path, options)
|
||||||
xhr.onload = function() {
|
.success(({ body }) => { success(body); })
|
||||||
onload(JSON.parse(xhr.responseText));
|
.fail(fail)
|
||||||
};
|
.run();
|
||||||
if(typeof onerror === 'function')
|
});
|
||||||
xhr.onerror = function() { onerror(); };
|
|
||||||
xhr.open('GET', get('api') + path);
|
|
||||||
if(noCache)
|
|
||||||
xhr.setRequestHeader('Cache-Control', 'no-cache');
|
|
||||||
xhr.send();
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
FutamiCommon.load = function(callback, url) {
|
FutamiCommon.load = function(url) {
|
||||||
if(typeof callback !== 'function')
|
return new Commitment((success, fail) => {
|
||||||
throw 'there must be a callback';
|
if(typeof url !== 'string' && 'FUTAMI_URL' in window)
|
||||||
if(typeof url !== 'string' && 'FUTAMI_URL' in window)
|
url = window.FUTAMI_URL + '?t=' + Date.now().toString();
|
||||||
url = window.FUTAMI_URL + '?t=' + Date.now().toString();
|
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest;
|
$xhr.get(url, { type: 'json', headers: { 'Cache-Control': 'no-cache' } })
|
||||||
xhr.onload = function() {
|
.success(({ body }) => { success(new FutamiCommon(body)); })
|
||||||
try {
|
.fail(fail)
|
||||||
callback(new FutamiCommon(JSON.parse(xhr.responseText)));
|
.run();
|
||||||
} catch(ex) {
|
});
|
||||||
callback(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xhr.onerror = function() {
|
|
||||||
callback(false);
|
|
||||||
};
|
|
||||||
xhr.open('GET', url);
|
|
||||||
xhr.setRequestHeader('Cache-Control', 'no-cache');
|
|
||||||
xhr.send();
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -122,9 +122,9 @@ var AmiContext = function(title, auth, loading) {
|
||||||
pub.textTriggers = textTriggers;
|
pub.textTriggers = textTriggers;
|
||||||
settings.watch('runJokeTriggers', function(value) {
|
settings.watch('runJokeTriggers', function(value) {
|
||||||
if(!textTriggers.hasTriggers())
|
if(!textTriggers.hasTriggers())
|
||||||
futami.getJson('texttriggers', function(trigInfos) {
|
futami.getJson('texttriggers')
|
||||||
textTriggers.addTriggers(trigInfos);
|
.success(textTriggers.addTriggers)
|
||||||
});
|
.run();
|
||||||
});
|
});
|
||||||
|
|
||||||
var styles = new AmiStyles;
|
var styles = new AmiStyles;
|
||||||
|
@ -187,11 +187,11 @@ var AmiContext = function(title, auth, loading) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
futami.getApiJson('/v1/emotes', function(emotes) {
|
futami.getApiJson('/v1/emotes').success(emotes => {
|
||||||
if(Array.isArray(emotes))
|
if(Array.isArray(emotes))
|
||||||
emoticons.load(emotes);
|
emoticons.load(emotes);
|
||||||
chat.emoticonList.render(emoticons);
|
chat.emoticonList.render(emoticons);
|
||||||
});
|
}).run();
|
||||||
});
|
});
|
||||||
|
|
||||||
var reconnecter = new AmiReconnecter(chat);
|
var reconnecter = new AmiReconnecter(chat);
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#include commitment.js
|
||||||
|
#include xhr.js
|
||||||
|
|
||||||
var AmiEEPROM = function(endPoint, getAuthLine) {
|
var AmiEEPROM = function(endPoint, getAuthLine) {
|
||||||
if(typeof endPoint !== 'string')
|
if(typeof endPoint !== 'string')
|
||||||
throw 'endPoint must be a string';
|
throw 'endPoint must be a string';
|
||||||
|
@ -14,16 +17,6 @@ var AmiEEPROM = function(endPoint, getAuthLine) {
|
||||||
|
|
||||||
let userAborted = false;
|
let userAborted = false;
|
||||||
let abortHandler;
|
let abortHandler;
|
||||||
let progressHandler;
|
|
||||||
|
|
||||||
const reportProgress = ev => {
|
|
||||||
if(progressHandler !== undefined)
|
|
||||||
progressHandler({
|
|
||||||
loaded: ev.loaded,
|
|
||||||
total: ev.total,
|
|
||||||
progress: ev.total <= 0 ? 0 : ev.loaded / ev.total,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
abort: () => {
|
abort: () => {
|
||||||
|
@ -31,133 +24,75 @@ var AmiEEPROM = function(endPoint, getAuthLine) {
|
||||||
if(typeof abortHandler === 'function')
|
if(typeof abortHandler === 'function')
|
||||||
abortHandler();
|
abortHandler();
|
||||||
},
|
},
|
||||||
onProgress: handler => {
|
start: progress => {
|
||||||
if(typeof handler !== 'function')
|
return new Commitment((success, fail) => {
|
||||||
throw 'handler must be a function';
|
|
||||||
progressHandler = handler;
|
|
||||||
},
|
|
||||||
start: (success, error) => {
|
|
||||||
const throwError = ex => {
|
|
||||||
if(typeof error === 'function')
|
|
||||||
error(ex);
|
|
||||||
else
|
|
||||||
console.error(ex);
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
if(typeof success !== 'function')
|
|
||||||
throw 'success must be a callback function';
|
|
||||||
|
|
||||||
if(userAborted)
|
if(userAborted)
|
||||||
throw 'File upload was cancelled by the user, it cannot be restarted.';
|
throw 'File upload was cancelled by the user, it cannot be restarted.';
|
||||||
|
|
||||||
try {
|
const reportProgress = typeof progress !== 'function' ? undefined : ev => {
|
||||||
const formData = new FormData;
|
progress({
|
||||||
formData.append('src', appId);
|
loaded: ev.loaded,
|
||||||
formData.append('file', fileInput);
|
total: ev.total,
|
||||||
|
progress: ev.total <= 0 ? 0 : ev.loaded / ev.total,
|
||||||
const xhr = new XMLHttpRequest;
|
|
||||||
abortHandler = () => { xhr.abort(); };
|
|
||||||
xhr.upload.onloadstart = reportProgress;
|
|
||||||
xhr.upload.onprogress = reportProgress;
|
|
||||||
xhr.upload.onloadend = reportProgress;
|
|
||||||
xhr.addEventListener('readystatechange', () => {
|
|
||||||
if(xhr.readyState !== XMLHttpRequest.DONE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const body = (() => {
|
|
||||||
try {
|
|
||||||
return JSON.parse(xhr.responseText);
|
|
||||||
} catch(ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
// user cancel
|
|
||||||
if(xhr.status === 0)
|
|
||||||
throw '';
|
|
||||||
|
|
||||||
if(body === null)
|
|
||||||
throw "The upload server didn't return the metadata for some reason.";
|
|
||||||
|
|
||||||
if(xhr.status !== 201)
|
|
||||||
throw body.english ?? body.error ?? `Upload failed with status code ${xhr.status}`;
|
|
||||||
|
|
||||||
body.isImage = () => body.type.indexOf('image/') === 0;
|
|
||||||
body.isVideo = () => body.type.indexOf('video/') === 0;
|
|
||||||
body.isAudio = () => body.type.indexOf('audio/') === 0;
|
|
||||||
body.isMedia = () => body.isImage() || body.isAudio() || body.isVideo();
|
|
||||||
|
|
||||||
success(Object.freeze(body));
|
|
||||||
} catch(ex) {
|
|
||||||
throwError(ex);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
xhr.open('POST', `${endPoint}/uploads`);
|
};
|
||||||
xhr.setRequestHeader('Authorization', getAuthLine());
|
|
||||||
xhr.send(formData);
|
|
||||||
} catch(ex) {
|
|
||||||
if(userAborted)
|
|
||||||
throw '';
|
|
||||||
|
|
||||||
console.error(ex);
|
const formData = new FormData;
|
||||||
throw ex;
|
formData.append('src', appId);
|
||||||
}
|
formData.append('file', fileInput);
|
||||||
} catch(ex) {
|
|
||||||
throwError(ex);
|
$xhr.post(`${endPoint}/uploads`, {
|
||||||
}
|
authed: true,
|
||||||
|
type: 'json',
|
||||||
|
upload: reportProgress,
|
||||||
|
abort: handler => abortHandler = handler
|
||||||
|
}, formData).fail(fail).success(({ status, body }) => {
|
||||||
|
try {
|
||||||
|
if(body === null)
|
||||||
|
throw "The upload server didn't return the metadata for some reason.";
|
||||||
|
|
||||||
|
if(status !== 201)
|
||||||
|
throw body.english ?? body.error ?? `Upload failed with status code ${status}`;
|
||||||
|
|
||||||
|
body.isImage = () => body.type.indexOf('image/') === 0;
|
||||||
|
body.isVideo = () => body.type.indexOf('video/') === 0;
|
||||||
|
body.isAudio = () => body.type.indexOf('audio/') === 0;
|
||||||
|
body.isMedia = () => body.isImage() || body.isAudio() || body.isVideo();
|
||||||
|
|
||||||
|
success(Object.freeze(body));
|
||||||
|
} catch(ex) {
|
||||||
|
if(userAborted)
|
||||||
|
throw '';
|
||||||
|
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}).run();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
delete: (fileInfo, success, error) => {
|
delete: fileInfo => {
|
||||||
const throwError = ex => {
|
return new Commitment((success, fail) => {
|
||||||
if(typeof error === 'function')
|
|
||||||
error(ex);
|
|
||||||
else
|
|
||||||
console.error(ex);
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
if(typeof fileInfo !== 'object')
|
if(typeof fileInfo !== 'object')
|
||||||
throw 'fileInfo must be an object';
|
throw 'fileInfo must be an object';
|
||||||
if(typeof fileInfo.urlf !== 'string')
|
if(typeof fileInfo.urlf !== 'string')
|
||||||
throw 'fileInfo.urlf must be a string';
|
throw 'fileInfo.urlf must be a string';
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest;
|
$xhr.delete(fileInfo.urlf, { authed: true, type: 'json' })
|
||||||
xhr.addEventListener('readystatechange', () => {
|
.success(({ status, body }) => {
|
||||||
if(xhr.readyState !== XMLHttpRequest.DONE)
|
if(status !== 204) {
|
||||||
return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const body = (() => {
|
|
||||||
try {
|
|
||||||
return JSON.parse(xhr.responseText);
|
|
||||||
} catch(ex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
if(xhr.status !== 204) {
|
|
||||||
if(body === null)
|
if(body === null)
|
||||||
throw `Delete failed with status code ${xhr.status}`;
|
throw `Delete failed with status code ${status}`;
|
||||||
|
|
||||||
throw body.english ?? body.error ?? `Delete failed with status code ${xhr.status}`;
|
throw body.english ?? body.error ?? `Delete failed with status code ${status}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(typeof success === 'function')
|
success();
|
||||||
success(body);
|
})
|
||||||
} catch(ex) {
|
.fail(fail)
|
||||||
throwError(ex);
|
.run();
|
||||||
}
|
});
|
||||||
});
|
|
||||||
xhr.open('DELETE', fileInfo.urlf);
|
|
||||||
xhr.setRequestHeader('Authorization', getAuthLine());
|
|
||||||
xhr.send();
|
|
||||||
} catch(ex) {
|
|
||||||
throwError(ex);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,36 +13,37 @@
|
||||||
(function() {
|
(function() {
|
||||||
var loading = new AmiLoadingOverlay(document.body, true);
|
var loading = new AmiLoadingOverlay(document.body, true);
|
||||||
|
|
||||||
FutamiCommon.load(function(futami) {
|
FutamiCommon.load()
|
||||||
if(typeof futami !== 'object') {
|
.success(futami => {
|
||||||
alert('Failed to load environment settings!');
|
window.futami = futami;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.futami = futami;
|
var auth = new AmiMisuzuAuth(futami.get('token'));
|
||||||
|
var refreshInfo = function(next) {
|
||||||
|
auth.refresh().success(token => {
|
||||||
|
if(token.ok === false) {
|
||||||
|
location.assign(futami.get('login') + '?legacy=1');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var auth = new AmiMisuzuAuth(futami.get('token'));
|
if(typeof next === 'function')
|
||||||
var refreshInfo = function(next) {
|
next(token.ok);
|
||||||
auth.refresh(function(token) {
|
}).run();
|
||||||
if(token.ok === false) {
|
};
|
||||||
location.assign(futami.get('login') + '?legacy=1');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(typeof next === 'function')
|
var ami = new AmiContext(futami.get('title'), auth, loading);
|
||||||
next(token.ok);
|
window.ami = ami;
|
||||||
|
|
||||||
|
setInterval(refreshInfo, 600000);
|
||||||
|
refreshInfo(function() {
|
||||||
|
Chat.Main(auth);
|
||||||
|
|
||||||
|
ami.sockChat.open();
|
||||||
|
window.addEventListener('beforeunload', () => ami.sockChat.close());
|
||||||
});
|
});
|
||||||
};
|
})
|
||||||
|
.fail(ex => {
|
||||||
var ami = new AmiContext(futami.get('title'), auth, loading);
|
console.log(ex);
|
||||||
window.ami = ami;
|
alert('Failed to load environment settings!');
|
||||||
|
})
|
||||||
setInterval(refreshInfo, 600000);
|
.run();
|
||||||
refreshInfo(function() {
|
|
||||||
Chat.Main(auth);
|
|
||||||
|
|
||||||
ami.sockChat.open();
|
|
||||||
window.addEventListener('beforeunload', () => ami.sockChat.close());
|
|
||||||
});
|
|
||||||
});
|
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -1,39 +1,36 @@
|
||||||
|
#include commitment.js
|
||||||
|
#include xhr.js
|
||||||
|
|
||||||
var AmiMisuzuAuth = function(refreshUrl) {
|
var AmiMisuzuAuth = function(refreshUrl) {
|
||||||
var userId = undefined,
|
let userId = null;
|
||||||
authToken = undefined;
|
let authMethod = 'Misuzu';
|
||||||
|
let authToken = null;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getUserId: function() { return userId; },
|
hasInfo: () => userId !== null && authToken !== null,
|
||||||
getAuthToken: function() { return authToken; },
|
getUserId: () => userId,
|
||||||
getInfo: function() {
|
getAuthToken: () => authToken,
|
||||||
|
getLine: () => `${authMethod} ${authToken}`,
|
||||||
|
getInfo: () => {
|
||||||
return {
|
return {
|
||||||
method: 'Misuzu',
|
method: authMethod,
|
||||||
token: authToken,
|
token: authToken,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
getHttpAuth: function() {
|
refresh: function() {
|
||||||
return 'Misuzu ' + authToken;
|
return new Commitment((success, fail) => {
|
||||||
},
|
$xhr.get(refreshUrl, { authed: true, type: 'json' })
|
||||||
refresh: function(callback) {
|
.success(({ body }) => {
|
||||||
var xhr = new XMLHttpRequest;
|
if(body.ok) {
|
||||||
xhr.onload = function() {
|
userId = body.usr.toString();
|
||||||
if(xhr.status === 200) {
|
authToken = body.tkn;
|
||||||
var data = JSON.parse(xhr.responseText);
|
}
|
||||||
if(data.ok === true) {
|
|
||||||
userId = data.usr.toString();
|
|
||||||
authToken = data.tkn;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(data);
|
success(body);
|
||||||
} else
|
})
|
||||||
callback({ok: null});
|
.fail(fail)
|
||||||
};
|
.run();
|
||||||
xhr.onerror = function() {
|
});
|
||||||
callback({ok: null});
|
|
||||||
};
|
|
||||||
xhr.open('GET', refreshUrl);
|
|
||||||
xhr.withCredentials = true;
|
|
||||||
xhr.send();
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -451,40 +451,41 @@ var Chat = (function () {
|
||||||
ami.sound.clearPacks();
|
ami.sound.clearPacks();
|
||||||
ami.sound.clearSoundLibrary();
|
ami.sound.clearSoundLibrary();
|
||||||
|
|
||||||
futami.getJson('sounds2', function(sounds) {
|
futami.getJson('sounds2')
|
||||||
if(typeof sounds !== 'object')
|
.success(function(sounds) {
|
||||||
return;
|
if(typeof sounds !== 'object')
|
||||||
|
return;
|
||||||
|
|
||||||
if(Array.isArray(sounds.library))
|
if(Array.isArray(sounds.library))
|
||||||
for(var i in sounds.library)
|
for(var i in sounds.library)
|
||||||
ami.sound.registerLibrarySound(sounds.library[i]);
|
ami.sound.registerLibrarySound(sounds.library[i]);
|
||||||
|
|
||||||
if(Array.isArray(sounds.packs)) {
|
if(Array.isArray(sounds.packs)) {
|
||||||
for(var i in sounds.packs)
|
for(var i in sounds.packs)
|
||||||
ami.sound.registerSoundPack(sounds.packs[i]);
|
ami.sound.registerSoundPack(sounds.packs[i]);
|
||||||
|
|
||||||
if(sounds.packs.length > 0 && !ami.settings.has('soundPack'))
|
if(sounds.packs.length > 0 && !ami.settings.has('soundPack'))
|
||||||
ami.settings.set('soundPack', sounds.packs[0].name);
|
ami.settings.set('soundPack', sounds.packs[0].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
var soundPackSetting = $id('chatSetting-spack');
|
var soundPackSetting = $id('chatSetting-spack');
|
||||||
if(soundPackSetting) {
|
if(soundPackSetting) {
|
||||||
while(soundPackSetting.options.length > 0)
|
while(soundPackSetting.options.length > 0)
|
||||||
soundPackSetting.options.remove(0);
|
soundPackSetting.options.remove(0);
|
||||||
|
|
||||||
ami.sound.forEachPack(function(pack) {
|
ami.sound.forEachPack(function(pack) {
|
||||||
var opt = document.createElement('option');
|
var opt = document.createElement('option');
|
||||||
opt.value = pack.getName();
|
opt.value = pack.getName();
|
||||||
opt.innerHTML = pack.getTitle();
|
opt.innerHTML = pack.getTitle();
|
||||||
soundPackSetting.appendChild(opt);
|
soundPackSetting.appendChild(opt);
|
||||||
|
|
||||||
if(ami.settings.get('soundPack') === '')
|
if(ami.settings.get('soundPack') === '')
|
||||||
ami.settings.set('soundPack', pack.getName());
|
ami.settings.set('soundPack', pack.getName());
|
||||||
});
|
});
|
||||||
|
|
||||||
soundPackSetting.value = ami.settings.get('soundPack');
|
soundPackSetting.value = ami.settings.get('soundPack');
|
||||||
}
|
}
|
||||||
});
|
}).run();
|
||||||
}
|
}
|
||||||
|
|
||||||
ami.sound.setMuted(value);
|
ami.sound.setMuted(value);
|
||||||
|
|
120
src/ami.js/xhr.js
Normal file
120
src/ami.js/xhr.js
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
#include commitment.js
|
||||||
|
|
||||||
|
const $xhr = (function() {
|
||||||
|
const send = function(method, url, options, body) {
|
||||||
|
if(options === undefined)
|
||||||
|
options = {};
|
||||||
|
else if(typeof options !== 'object')
|
||||||
|
throw 'options must be undefined or an object';
|
||||||
|
|
||||||
|
Object.freeze(options);
|
||||||
|
|
||||||
|
const xhr = new XMLHttpRequest;
|
||||||
|
const requestHeaders = new Map;
|
||||||
|
|
||||||
|
if('headers' in options && typeof options.headers === 'object')
|
||||||
|
for(const name in options.headers)
|
||||||
|
if(options.headers.hasOwnProperty(name))
|
||||||
|
requestHeaders.set(name.toLowerCase(), options.headers[name]);
|
||||||
|
|
||||||
|
if(typeof options.download === 'function') {
|
||||||
|
xhr.onloadstart = ev => options.download(ev);
|
||||||
|
xhr.onprogress = ev => options.download(ev);
|
||||||
|
xhr.onloadend = ev => options.download(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(typeof options.upload === 'function') {
|
||||||
|
xhr.upload.onloadstart = ev => options.upload(ev);
|
||||||
|
xhr.upload.onprogress = ev => options.upload(ev);
|
||||||
|
xhr.upload.onloadend = ev => options.upload(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(options.authed)
|
||||||
|
xhr.withCredentials = true;
|
||||||
|
|
||||||
|
if(typeof options.timeout === 'number')
|
||||||
|
xhr.timeout = options.timeout;
|
||||||
|
|
||||||
|
if(typeof options.abort === 'function')
|
||||||
|
options.abort(() => xhr.abort());
|
||||||
|
|
||||||
|
if(typeof options.xhr === 'function')
|
||||||
|
options.xhr(() => xhr);
|
||||||
|
|
||||||
|
if(typeof body === 'object') {
|
||||||
|
if(body instanceof FormData) {
|
||||||
|
// content-type is implicitly set
|
||||||
|
} else if(body instanceof Blob || body instanceof ArrayBuffer
|
||||||
|
|| body instanceof DataView || body instanceof Uint8Array) {
|
||||||
|
if(!requestHeaders.has('content-type'))
|
||||||
|
requestHeaders.set('content-type', 'application/octet-stream');
|
||||||
|
} else if(!requestHeaders.has('content-type')) {
|
||||||
|
const bodyParts = [];
|
||||||
|
for(const name in body)
|
||||||
|
if(body.hasOwnProperty(name))
|
||||||
|
bodyParts.push(encodeURIComponent(name) + '=' + encodeURIComponent(body[name]));
|
||||||
|
body = bodyParts.join('&');
|
||||||
|
requestHeaders.set('content-type', 'application/x-www-form-urlencoded');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Commitment((success, fail) => {
|
||||||
|
xhr.onload = ev => {
|
||||||
|
const headers = (headersString => {
|
||||||
|
const headers = new Map;
|
||||||
|
|
||||||
|
const raw = headersString.trim().split(/[\r\n]+/);
|
||||||
|
for(const name in raw)
|
||||||
|
if(raw.hasOwnProperty(name)) {
|
||||||
|
const parts = raw[name].split(': ');
|
||||||
|
headers.set(parts.shift(), parts.join(': '));
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
})(xhr.getAllResponseHeaders());
|
||||||
|
|
||||||
|
success({
|
||||||
|
get ev() { return ev; },
|
||||||
|
get xhr() { return xhr; },
|
||||||
|
|
||||||
|
get status() { return xhr.status; },
|
||||||
|
get headers() { return headers; },
|
||||||
|
get body() { return xhr.response; },
|
||||||
|
get text() { return xhr.responseText; },
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onabort = ev => fail({
|
||||||
|
abort: true,
|
||||||
|
xhr: xhr,
|
||||||
|
ev: ev,
|
||||||
|
});
|
||||||
|
|
||||||
|
xhr.onerror = ev => fail({
|
||||||
|
abort: false,
|
||||||
|
xhr: xhr,
|
||||||
|
ev: ev,
|
||||||
|
});
|
||||||
|
|
||||||
|
xhr.open(method, url);
|
||||||
|
|
||||||
|
if(typeof options.type === 'string')
|
||||||
|
xhr.responseType = options.type;
|
||||||
|
|
||||||
|
requestHeaders.forEach((value, name) => {
|
||||||
|
xhr.setRequestHeader(name, requestHeaders[name]);
|
||||||
|
});
|
||||||
|
|
||||||
|
xhr.send(body);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
send: send,
|
||||||
|
get: (url, options, body) => send('GET', url, options, body),
|
||||||
|
post: (url, options, body) => send('POST', url, options, body),
|
||||||
|
delete: (url, options, body) => send('DELETE', url, options, body),
|
||||||
|
patch: (url, options, body) => send('PATCH', url, options, body),
|
||||||
|
put: (url, options, body) => send('PUT', url, options, body),
|
||||||
|
};
|
||||||
|
})();
|
|
@ -1,13 +1,9 @@
|
||||||
#include common.js
|
#include common.js
|
||||||
#include eeprom.js
|
#include eeprom.js
|
||||||
|
|
||||||
var eepromAppl = 1,
|
|
||||||
eepromSupportImageEmbed = true,
|
|
||||||
eepromSupportAudioEmbed = true,
|
|
||||||
eepromSupportVideoEmbed = true;
|
|
||||||
var eepromInitialise = function(auth) {
|
var eepromInitialise = function(auth) {
|
||||||
window.eepromHistory = {};
|
window.eepromHistory = {};
|
||||||
window.eepromClient = new AmiEEPROM(futami.get('eeprom2'), auth.getHttpAuth);
|
window.eepromClient = new AmiEEPROM(futami.get('eeprom2'), auth.getLine);
|
||||||
|
|
||||||
window.eepromUploadsTable = $id('uploadHistory');
|
window.eepromUploadsTable = $id('uploadHistory');
|
||||||
$id('uploadSelector').onchange = function() {
|
$id('uploadSelector').onchange = function() {
|
||||||
|
@ -88,27 +84,25 @@ var eepromFileUpload = function(file) {
|
||||||
|
|
||||||
var uploadTask = window.eepromClient.create(file);
|
var uploadTask = window.eepromClient.create(file);
|
||||||
|
|
||||||
uploadTask.onProgress(function(progressInfo) {
|
|
||||||
progBar.style.width = `${progressInfo.progress * 100}%`;
|
|
||||||
});
|
|
||||||
|
|
||||||
name.onclick = function(ev) {
|
name.onclick = function(ev) {
|
||||||
if(ev.shiftKey) {
|
if(ev.shiftKey) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
var fileInfo = window.eepromHistory[name.getAttribute('data-eeprom-id') || ''];
|
var fileInfo = window.eepromHistory[name.getAttribute('data-eeprom-id') || ''];
|
||||||
|
|
||||||
if(fileInfo) {
|
if(fileInfo) {
|
||||||
window.eepromClient.delete(
|
window.eepromClient.delete(fileInfo)
|
||||||
fileInfo,
|
.success(() => { window.eepromUploadsTable.deleteRow(uploadEntryWrap.rowIndex); })
|
||||||
() => { uploadHistory.deleteRow(uploadEntryWrap.rowIndex); },
|
.fail(ex => {
|
||||||
window.alert
|
console.error(ex);
|
||||||
);
|
window.alert(ex);
|
||||||
|
})
|
||||||
|
.run();
|
||||||
} else uploadTask.abort();
|
} else uploadTask.abort();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
uploadTask.start(
|
uploadTask.start(progressInfo => { progBar.style.width = `${progressInfo.progress * 100}%`; })
|
||||||
fileInfo => {
|
.success(fileInfo => {
|
||||||
window.eepromHistory[fileInfo.id] = fileInfo;
|
window.eepromHistory[fileInfo.id] = fileInfo;
|
||||||
name.style.textDecoration = null;
|
name.style.textDecoration = null;
|
||||||
name.setAttribute('data-eeprom-id', fileInfo.id);
|
name.setAttribute('data-eeprom-id', fileInfo.id);
|
||||||
|
@ -117,19 +111,19 @@ var eepromFileUpload = function(file) {
|
||||||
|
|
||||||
var insertText = location.protocol + fileInfo.url;
|
var insertText = location.protocol + fileInfo.url;
|
||||||
|
|
||||||
if(eepromSupportImageEmbed && fileInfo.isImage())
|
if(fileInfo.isImage())
|
||||||
insertText = '[img]' + fileInfo.url + '[/img]';
|
insertText = '[img]' + fileInfo.url + '[/img]';
|
||||||
else if(eepromSupportAudioEmbed && fileInfo.isAudio())
|
else if(fileInfo.isAudio())
|
||||||
insertText = '[audio]' + fileInfo.url + '[/audio]';
|
insertText = '[audio]' + fileInfo.url + '[/audio]';
|
||||||
else if(eepromSupportVideoEmbed && fileInfo.isVideo())
|
else if(fileInfo.isVideo())
|
||||||
insertText = '[video]' + fileInfo.url + '[/video]';
|
insertText = '[video]' + fileInfo.url + '[/video]';
|
||||||
|
|
||||||
ami.chat.inputBox.insert(insertText);
|
ami.chat.inputBox.insert(insertText);
|
||||||
},
|
})
|
||||||
ex => {
|
.fail(ex => {
|
||||||
if(ex !== '')
|
if(ex !== '')
|
||||||
alert(ex);
|
alert(ex);
|
||||||
uploadHistory.deleteRow(uploadEntryWrap.rowIndex);
|
window.eepromUploadsTable.deleteRow(uploadEntryWrap.rowIndex);
|
||||||
},
|
})
|
||||||
);
|
.run();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue