Imported core stuff from Misuzu.
This commit is contained in:
parent
5c71b34c24
commit
9841468f59
35 changed files with 314 additions and 399 deletions
build.js
src/mami.js
array.js
audio
colpick
common.jsconman.jscontrols
eeprom
emotes
html.jsmain.jsmszauth.jsparsing.jssettings
sidebar
sound
themes.jsui
uniqstr.jsutility.jsweeb.jsxhr.js
3
build.js
3
build.js
|
@ -14,7 +14,8 @@ const exec = require('util').promisify(require('child_process').exec);
|
|||
debug: isDebug,
|
||||
swc: {
|
||||
es: 'es2021',
|
||||
jsx: '$er',
|
||||
jsx: '$element',
|
||||
jsxf: '$fragment',
|
||||
},
|
||||
housekeep: [
|
||||
pathJoin(__dirname, 'public', 'assets'),
|
||||
|
|
27
src/mami.js/array.js
Normal file
27
src/mami.js/array.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
const $arrayRemoveAt = function(array, index) {
|
||||
array.splice(index, 1);
|
||||
};
|
||||
|
||||
const $arrayRemoveValue = function(array, item) {
|
||||
let index;
|
||||
while(array.length > 0 && (index = array.indexOf(item)) >= 0)
|
||||
$arrayRemoveAt(array, index);
|
||||
};
|
||||
|
||||
const $arrayRemoveAny = function(array, predicate) {
|
||||
let index;
|
||||
while(array.length > 0 && (index = array.findIndex(predicate)) >= 0)
|
||||
$arrayRemoveAt(array, index);
|
||||
};
|
||||
|
||||
const $arrayShuffle = function(array) {
|
||||
if(array.length < 2)
|
||||
return;
|
||||
|
||||
for(let i = array.length - 1; i > 0; --i) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
const tmp = array[i];
|
||||
array[i] = array[j];
|
||||
array[j] = tmp;
|
||||
}
|
||||
};
|
|
@ -1,11 +1,10 @@
|
|||
#include srle.js
|
||||
#include utility.js
|
||||
|
||||
const MamiDetectAutoPlaySource = '/+NIxA!!FhpbmcA#PA$wA@fgAV$#q$#/$#A#OUxBTUUzLjEwMAIeA!)UCCQC8CIA@gA@H49wpKWgA!%&/+MYxA$NIA$ExBTUUzLjEwMFV^%/+MYxDsA@NIA$FV&&/+MYxHYA@NIA$FV&&';
|
||||
|
||||
const MamiDetectAutoPlay = async () => {
|
||||
try {
|
||||
await $e('audio', { src: 'data:audio/mpeg;base64,' + MamiSRLE.decode(MamiDetectAutoPlaySource) }).play();
|
||||
await $element('audio', { src: 'data:audio/mpeg;base64,' + MamiSRLE.decode(MamiDetectAutoPlaySource) }).play();
|
||||
} catch(ex) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#include xhr.js
|
||||
#include audio/source.js
|
||||
|
||||
const MamiAudioContext = function() {
|
||||
|
@ -62,8 +61,8 @@ const MamiAudioContext = function() {
|
|||
if(ctx === undefined)
|
||||
return undefined;
|
||||
|
||||
const result = await $x.get(url, { type: 'arraybuffer' });
|
||||
return await ctx.decodeAudioData(result.body);
|
||||
const { body } = await $xhr.get(url, { type: 'arraybuffer' });
|
||||
return await ctx.decodeAudioData(body);
|
||||
},
|
||||
|
||||
createSource: (buffer, reverse) => {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include args.js
|
||||
#include colour.js
|
||||
#include utility.js
|
||||
#include controls/tabs.js
|
||||
#include colpick/tgrid.jsx
|
||||
#include colpick/tpresets.jsx
|
||||
|
@ -101,8 +100,8 @@ const MamiColourPicker = function(options) {
|
|||
},
|
||||
onRemove: ctx => {
|
||||
const name = ctx.info.name;
|
||||
$rq(`.colpick-tab-${name}-button`);
|
||||
$rq(`.colpick-tab-${name}-container`);
|
||||
$query(`.colpick-tab-${name}-button`)?.remove();
|
||||
$query(`.colpick-tab-${name}-container`)?.remove();
|
||||
},
|
||||
onSwitch: ctx => {
|
||||
if(ctx.from !== undefined) {
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include xhr.js
|
||||
|
||||
const FutamiCommon = function(vars) {
|
||||
vars = vars || {};
|
||||
|
||||
|
@ -15,14 +13,16 @@ const FutamiCommon = function(vars) {
|
|||
if(noCache)
|
||||
options.headers = { 'Cache-Control': 'no-cache' };
|
||||
|
||||
return (await $x.get(get(name), options)).body;
|
||||
const { body } = await $xhr.get(get(name), options);
|
||||
return body;
|
||||
},
|
||||
getApiJson: async (path, noCache) => {
|
||||
const options = { type: 'json' };
|
||||
if(noCache)
|
||||
options.headers = { 'Cache-Control': 'no-cache' };
|
||||
|
||||
return (await $x.get(get('api') + path, options)).body;
|
||||
const { body } = await $xhr.get(get('api') + path, options);
|
||||
return body;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -31,7 +31,7 @@ FutamiCommon.load = async url => {
|
|||
if(typeof url !== 'string' && 'FUTAMI_URL' in window)
|
||||
url = window.FUTAMI_URL + '?t=' + Date.now().toString();
|
||||
|
||||
const { body } = await $x.get(url, {
|
||||
const { body } = await $xhr.get(url, {
|
||||
type: 'json',
|
||||
headers: {
|
||||
'Cache-Control': 'no-cache'
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include awaitable.js
|
||||
#include utility.js
|
||||
|
||||
const MamiConnectionManager = function(client, settings, urls, eventTarget) {
|
||||
const validateClient = value => {
|
||||
|
@ -42,7 +41,7 @@ const MamiConnectionManager = function(client, settings, urls, eventTarget) {
|
|||
url = undefined;
|
||||
};
|
||||
|
||||
$as(urls);
|
||||
$arrayShuffle(urls);
|
||||
|
||||
const attempt = () => {
|
||||
started = Date.now();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include animate.js
|
||||
#include args.js
|
||||
#include utility.js
|
||||
|
||||
const MamiMessageBoxContainer = function() {
|
||||
const container = <div class="msgbox-container"/>;
|
||||
|
@ -229,7 +228,7 @@ const MamiMessageBoxDialog = function(info) {
|
|||
end: () => { dialog.style.opacity = '0'; },
|
||||
});
|
||||
|
||||
$r(dialog);
|
||||
dialog.remove();
|
||||
},
|
||||
cancel: () => {
|
||||
doReject();
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include args.js
|
||||
#include uniqstr.js
|
||||
|
||||
const MamiTabsControl = function(options) {
|
||||
options = MamiArgs('options', options, define => {
|
||||
|
@ -21,8 +20,6 @@ const MamiTabsControl = function(options) {
|
|||
element = elementInfo;
|
||||
} else if('element' in elementInfo) {
|
||||
element = elementInfo.element;
|
||||
} else if('getElement' in elementInfo) {
|
||||
element = elementInfo.getElement();
|
||||
} else throw 'elementInfo is not a valid type';
|
||||
|
||||
if(!(element instanceof Element))
|
||||
|
@ -126,7 +123,7 @@ const MamiTabsControl = function(options) {
|
|||
if(tabId !== undefined)
|
||||
throw 'tabInfo has already been added';
|
||||
|
||||
tabId = MamiUniqueStr(8);
|
||||
tabId = $rngs(8);
|
||||
tabs.set(tabId, tabInfo);
|
||||
|
||||
if(title !== 'string' && 'title' in tabInfo)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include args.js
|
||||
#include utility.js
|
||||
|
||||
const MamiViewsControl = function(options) {
|
||||
options = MamiArgs('options', options, define => {
|
||||
|
@ -17,8 +16,6 @@ const MamiViewsControl = function(options) {
|
|||
element = elementInfo;
|
||||
} else if('element' in elementInfo) {
|
||||
element = elementInfo.element;
|
||||
} else if('getElement' in elementInfo) {
|
||||
element = elementInfo.getElement();
|
||||
} else throw 'elementInfo is not a valid type';
|
||||
|
||||
if(!(element instanceof Element))
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include xhr.js
|
||||
|
||||
const MamiEEPROM = function(endPoint, getAuthLine) {
|
||||
if(typeof endPoint !== 'string')
|
||||
throw 'endPoint must be a string';
|
||||
|
@ -40,7 +38,7 @@ const MamiEEPROM = function(endPoint, getAuthLine) {
|
|||
formData.append('src', appId);
|
||||
formData.append('file', fileInput);
|
||||
|
||||
const { status, body } = await $x.post(`${endPoint}/uploads`, {
|
||||
const { status, body } = await $xhr.post(`${endPoint}/uploads`, {
|
||||
type: 'json',
|
||||
headers: {
|
||||
Authorization: getAuthLine(),
|
||||
|
@ -77,7 +75,7 @@ const MamiEEPROM = function(endPoint, getAuthLine) {
|
|||
if(typeof fileInfo.urlf !== 'string')
|
||||
throw 'fileInfo.urlf must be a string';
|
||||
|
||||
const { status, body } = await $x.delete(fileInfo.urlf, {
|
||||
const { status, body } = await $xhr.delete(fileInfo.urlf, {
|
||||
type: 'json',
|
||||
headers: {
|
||||
Authorization: getAuthLine(),
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include concurrent.js
|
||||
#include hash.js
|
||||
#include xhr.js
|
||||
|
||||
const MamiEEPROMv2 = function(baseUrl, getAuthLine, poolName) {
|
||||
if(typeof baseUrl !== 'string')
|
||||
|
@ -37,7 +36,7 @@ const MamiEEPROMv2 = function(baseUrl, getAuthLine, poolName) {
|
|||
params.append('name', name);
|
||||
params.append('hash', await MamiHash(buffer));
|
||||
|
||||
const { status, body } = await $x.post(`${baseUrl}/v1/storage/pools/${poolName}/uploads`, {
|
||||
const { status, body } = await $xhr.post(`${baseUrl}/v1/storage/pools/${poolName}/uploads`, {
|
||||
type: 'json',
|
||||
headers: {
|
||||
Authorization: getAuthLine(),
|
||||
|
@ -57,7 +56,7 @@ const MamiEEPROMv2 = function(baseUrl, getAuthLine, poolName) {
|
|||
const offset = size * index;
|
||||
buffer = buffer.subarray(offset, Math.min(buffer.length, offset + size));
|
||||
|
||||
const { status, body } = await $x.put(taskInfo.task_url, {
|
||||
const { status, body } = await $xhr.put(taskInfo.task_url, {
|
||||
type: 'json',
|
||||
headers: {
|
||||
'X-Content-Index': index,
|
||||
|
@ -73,7 +72,7 @@ const MamiEEPROMv2 = function(baseUrl, getAuthLine, poolName) {
|
|||
};
|
||||
|
||||
const finishTask = async (taskInfo) => {
|
||||
const { status, body } = await $x.post(`${baseUrl}/v1/storage/tasks/${taskInfo.task_id}`, { type: 'json' });
|
||||
const { status, body } = await $xhr.post(`${baseUrl}/v1/storage/tasks/${taskInfo.task_id}`, { type: 'json' });
|
||||
if(body === null)
|
||||
throw "Could not complete upload task for some reason.";
|
||||
|
||||
|
@ -146,7 +145,7 @@ const MamiEEPROMv2 = function(baseUrl, getAuthLine, poolName) {
|
|||
if(typeof fileInfo.id !== 'string')
|
||||
throw 'fileInfo.id must be a string';
|
||||
|
||||
const { status, body } = await $x.delete(`${baseUrl}/v1/storage/uploads/${fileInfo.id}`, {
|
||||
const { status, body } = await $xhr.delete(`${baseUrl}/v1/storage/uploads/${fileInfo.id}`, {
|
||||
type: 'json',
|
||||
headers: {
|
||||
Authorization: getAuthLine(),
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include args.js
|
||||
#include utility.js
|
||||
|
||||
const MamiEmotePicker = function(args) {
|
||||
args = MamiArgs('args', args, define => {
|
||||
|
@ -35,7 +34,7 @@ const MamiEmotePicker = function(args) {
|
|||
</div>;
|
||||
|
||||
const buildList = () => {
|
||||
$rc(listElem);
|
||||
$removeChildren(listElem);
|
||||
|
||||
for(const emote of emotes)
|
||||
listElem.appendChild(<button class="emopick-emote" type="button" title={`:${emote.strings[0]}:`} data-strings={emote.strings.join(' ')} onclick={() => {
|
||||
|
|
139
src/mami.js/html.js
Normal file
139
src/mami.js/html.js
Normal file
|
@ -0,0 +1,139 @@
|
|||
const $id = document.getElementById.bind(document);
|
||||
const $query = document.querySelector.bind(document);
|
||||
const $queryAll = document.querySelectorAll.bind(document);
|
||||
const $text = document.createTextNode.bind(document);
|
||||
|
||||
const $insertBefore = function(target, element) {
|
||||
target.parentNode.insertBefore(element, target);
|
||||
};
|
||||
|
||||
const $appendChild = function(element, child) {
|
||||
switch(typeof child) {
|
||||
case 'undefined':
|
||||
break;
|
||||
|
||||
case 'string':
|
||||
element.appendChild($text(child));
|
||||
break;
|
||||
|
||||
case 'function':
|
||||
$appendChild(element, child());
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
if(child === null)
|
||||
break;
|
||||
|
||||
if(child instanceof Node)
|
||||
element.appendChild(child);
|
||||
else if(child?.element instanceof Node)
|
||||
element.appendChild(child.element);
|
||||
else if(typeof child?.toString === 'function')
|
||||
element.appendChild($text(child.toString()));
|
||||
break;
|
||||
|
||||
default:
|
||||
element.appendChild($text(child.toString()));
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
const $appendChildren = function(element, ...children) {
|
||||
for(const child of children)
|
||||
$appendChild(element, child);
|
||||
};
|
||||
|
||||
const $removeChildren = function(element) {
|
||||
while(element.lastChild)
|
||||
element.removeChild(element.lastChild);
|
||||
};
|
||||
|
||||
const $fragment = function(props, ...children) {
|
||||
const fragment = document.createDocumentFragment();
|
||||
$appendChildren(fragment, ...children);
|
||||
return fragment;
|
||||
};
|
||||
|
||||
const $element = function(type, props, ...children) {
|
||||
if(typeof type === 'function')
|
||||
return new type(props ?? {}, ...children);
|
||||
|
||||
const element = document.createElement(type ?? 'div');
|
||||
|
||||
if(props)
|
||||
for(let key in props) {
|
||||
const prop = props[key];
|
||||
if(prop === undefined || prop === null)
|
||||
continue;
|
||||
|
||||
switch(typeof prop) {
|
||||
case 'function':
|
||||
if(key.substring(0, 2) === 'on')
|
||||
key = key.substring(2).toLowerCase();
|
||||
element.addEventListener(key, prop);
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
if(prop instanceof Array) {
|
||||
if(key === 'class')
|
||||
key = 'classList';
|
||||
|
||||
const attr = element[key];
|
||||
let addFunc = null;
|
||||
|
||||
if(attr instanceof Array)
|
||||
addFunc = attr.push.bind(attr);
|
||||
else if(attr instanceof DOMTokenList)
|
||||
addFunc = attr.add.bind(attr);
|
||||
|
||||
if(addFunc !== null) {
|
||||
for(let j = 0; j < prop.length; ++j)
|
||||
addFunc(prop[j]);
|
||||
} else {
|
||||
if(key === 'classList')
|
||||
key = 'class';
|
||||
element.setAttribute(key, prop.toString());
|
||||
}
|
||||
} else {
|
||||
if(key === 'class' || key === 'className')
|
||||
key = 'classList';
|
||||
|
||||
let setFunc = null;
|
||||
if(element[key] instanceof DOMTokenList)
|
||||
setFunc = (ak, av) => { if(av) element[key].add(ak); };
|
||||
else if(element[key] instanceof CSSStyleDeclaration)
|
||||
setFunc = (ak, av) => {
|
||||
if(ak.includes('-'))
|
||||
element[key].setProperty(ak, av);
|
||||
else
|
||||
element[key][ak] = av;
|
||||
};
|
||||
else
|
||||
setFunc = (ak, av) => { element[key][ak] = av; };
|
||||
|
||||
for(const attrKey in prop) {
|
||||
const attrValue = prop[attrKey];
|
||||
if(attrValue)
|
||||
setFunc(attrKey, attrValue);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
if(prop)
|
||||
element.setAttribute(key, '');
|
||||
break;
|
||||
|
||||
default:
|
||||
if(key === 'className')
|
||||
key = 'class';
|
||||
|
||||
element.setAttribute(key, prop.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$appendChildren(element, ...children);
|
||||
|
||||
return element;
|
||||
};
|
|
@ -1,5 +1,10 @@
|
|||
window.Umi = { UI: {} };
|
||||
|
||||
#include array.js
|
||||
#include html.js
|
||||
#include uniqstr.js
|
||||
#include xhr.js
|
||||
|
||||
#include animate.js
|
||||
#include args.js
|
||||
#include awaitable.js
|
||||
|
@ -14,9 +19,7 @@ window.Umi = { UI: {} };
|
|||
#include parsing.js
|
||||
#include themes.js
|
||||
#include txtrigs.js
|
||||
#include uniqstr.js
|
||||
#include users.js
|
||||
#include utility.js
|
||||
#include weeb.js
|
||||
#include audio/autoplay.js
|
||||
#include chatform/form.jsx
|
||||
|
@ -262,13 +265,9 @@ const MamiInit = async args => {
|
|||
text: title,
|
||||
createdButton: button => {
|
||||
button.element.id = `umi-menu-icons-${baseId}`;
|
||||
button.element.append($e({
|
||||
attrs: { className: `sidebar__selector-mode--${baseId}` },
|
||||
}));
|
||||
button.element.append($element('div', { className: `sidebar__selector-mode--${baseId}` }));
|
||||
},
|
||||
element: $e({
|
||||
attrs: { 'class': `sidebar__menu--${baseId}`, id: `umi-menus-${baseId}` }
|
||||
}),
|
||||
element: $element('div', { 'class': `sidebar__menu--${baseId}`, id: `umi-menus-${baseId}` }),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -313,7 +312,7 @@ const MamiInit = async args => {
|
|||
if(bbCode.tag === 'color') {
|
||||
if(colourPicker === undefined) {
|
||||
colourPicker = new MamiColourPicker({ presets: futami.get('colours') });
|
||||
layout.getElement().appendChild(colourPicker.element);
|
||||
layout.element.appendChild(colourPicker.element);
|
||||
}
|
||||
|
||||
if(colourPickerVisible) {
|
||||
|
@ -339,19 +338,19 @@ const MamiInit = async args => {
|
|||
});
|
||||
|
||||
settings.watch('style', ev => {
|
||||
for(const className of layout.getElement().classList)
|
||||
for(const className of layout.element.classList)
|
||||
if(className.startsWith('umi--'))
|
||||
layout.getElement().classList.remove(className);
|
||||
layout.getElement().classList.add(`umi--${ev.detail.value}`);
|
||||
layout.element.classList.remove(className);
|
||||
layout.element.classList.add(`umi--${ev.detail.value}`);
|
||||
|
||||
UmiThemeApply(ev.detail.value);
|
||||
});
|
||||
settings.watch('compactView', ev => {
|
||||
layout.getElement().classList.toggle('chat--compact', ev.detail.value);
|
||||
layout.getInterface().getMessageList().getElement().classList.toggle('chat--compact', ev.detail.value);
|
||||
layout.element.classList.toggle('chat--compact', ev.detail.value);
|
||||
layout.interface.messageList.element.classList.toggle('chat--compact', ev.detail.value);
|
||||
});
|
||||
settings.watch('preventOverflow', ev => { args.parent.classList.toggle('prevent-overflow', ev.detail.value); });
|
||||
settings.watch('doNotMarkLinksAsVisited', ev => { layout.getInterface().getMessageList().getElement().classList.toggle('mami-do-not-mark-links-as-visited', ev.detail.value); });
|
||||
settings.watch('doNotMarkLinksAsVisited', ev => { layout.interface.messageList.element.classList.toggle('mami-do-not-mark-links-as-visited', ev.detail.value); });
|
||||
settings.watch('newLineOnEnter', ev => { chatForm.input.newLineOnEnter = ev.detail.value; });
|
||||
settings.watch('expandTextBox', ev => { chatForm.input.growInputField = ev.detail.value; });
|
||||
|
||||
|
@ -705,7 +704,7 @@ const MamiInit = async args => {
|
|||
getEmotes: () => MamiEmotes.all(Umi.User.getCurrentUser().perms.rank),
|
||||
setKeepOpenOnPick: value => { settings.set('keepEmotePickerOpen', value); },
|
||||
});
|
||||
layout.getElement().appendChild(emotePicker.element);
|
||||
layout.element.appendChild(emotePicker.element);
|
||||
settings.watch('keepEmotePickerOpen', ev => { emotePicker.keepOpenOnPick = ev.detail.value; });
|
||||
}
|
||||
|
||||
|
@ -799,16 +798,13 @@ const MamiInit = async args => {
|
|||
}
|
||||
};
|
||||
|
||||
const uploadForm = $e({
|
||||
tag: 'input',
|
||||
attrs: {
|
||||
type: 'file',
|
||||
multiple: true,
|
||||
style: { display: 'none' },
|
||||
onchange: ev => {
|
||||
for(const file of ev.target.files)
|
||||
doUpload(file);
|
||||
},
|
||||
const uploadForm = $element('input', {
|
||||
type: 'file',
|
||||
multiple: true,
|
||||
style: { display: 'none' },
|
||||
onchange: ev => {
|
||||
for(const file of ev.target.files)
|
||||
doUpload(file);
|
||||
},
|
||||
});
|
||||
args.parent.appendChild(uploadForm);
|
||||
|
@ -981,18 +977,16 @@ const MamiDbgCreateFloatingInstance = async () => {
|
|||
if(!FUTAMI_DEBUG)
|
||||
return;
|
||||
|
||||
const prefix = MamiUniqueStr(8);
|
||||
const parent = $e({
|
||||
attrs: {
|
||||
style: {
|
||||
position: 'absolute',
|
||||
bottom: '100px',
|
||||
right: '100px',
|
||||
zIndex: '9001',
|
||||
width: '640px',
|
||||
height: '480px',
|
||||
background: '#0f0',
|
||||
},
|
||||
const prefix = $rngs(8);
|
||||
const parent = $element('div', {
|
||||
style: {
|
||||
position: 'absolute',
|
||||
bottom: '100px',
|
||||
right: '100px',
|
||||
zIndex: '9001',
|
||||
width: '640px',
|
||||
height: '480px',
|
||||
background: '#0f0',
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include common.js
|
||||
#include xhr.js
|
||||
|
||||
const MamiMisuzuAuth = (() => {
|
||||
let userId = null;
|
||||
|
@ -18,7 +17,7 @@ const MamiMisuzuAuth = (() => {
|
|||
};
|
||||
},
|
||||
update: async () => {
|
||||
const { body } = await $x.get(futami.get('token'), { authed: true, type: 'json' });
|
||||
const { body } = await $xhr.get(futami.get('token'), { authed: true, type: 'json' });
|
||||
if(body.ok) {
|
||||
userId = body.usr.toString();
|
||||
authToken = body.tkn;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include utility.js
|
||||
|
||||
if(!Umi.Parser) Umi.Parser = {};
|
||||
if(!Umi.Parser.SockChatBBcode) Umi.Parser.SockChatBBcode = {};
|
||||
|
||||
|
@ -146,8 +144,9 @@ Umi.Parsing = (function() {
|
|||
};
|
||||
};
|
||||
const motivFrame = function(texts, body) {
|
||||
return $e({
|
||||
attrs: {
|
||||
return $element(
|
||||
'div',
|
||||
{
|
||||
style: {
|
||||
display: 'inline-block',
|
||||
textAlign: 'center',
|
||||
|
@ -158,48 +157,46 @@ Umi.Parsing = (function() {
|
|||
lineHeight: '1.4em',
|
||||
},
|
||||
},
|
||||
child: [
|
||||
$element(
|
||||
'div',
|
||||
{
|
||||
tag: 'div',
|
||||
attrs: {
|
||||
style: {
|
||||
border: '3px double #fff',
|
||||
maxWidth: '50vw',
|
||||
maxHeight: '50vh',
|
||||
marginTop: '30px',
|
||||
marginLeft: '50px',
|
||||
marginRight: '50px',
|
||||
boxSizing: 'content-box',
|
||||
display: 'inline-block',
|
||||
},
|
||||
},
|
||||
child: body,
|
||||
},
|
||||
{
|
||||
tag: 'h1',
|
||||
child: texts.top,
|
||||
attrs: {
|
||||
style: {
|
||||
color: '#fff',
|
||||
textDecoration: 'none !important',
|
||||
margin: '10px',
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
style: {
|
||||
border: '3px double #fff',
|
||||
maxWidth: '50vw',
|
||||
maxHeight: '50vh',
|
||||
marginTop: '30px',
|
||||
marginLeft: '50px',
|
||||
marginRight: '50px',
|
||||
boxSizing: 'content-box',
|
||||
display: 'inline-block',
|
||||
},
|
||||
},
|
||||
body
|
||||
),
|
||||
$element(
|
||||
'h1',
|
||||
{
|
||||
tag: 'p',
|
||||
child: texts.bottom,
|
||||
attrs: {
|
||||
style: {
|
||||
color: '#fff',
|
||||
textDecoration: 'none !important',
|
||||
margin: '10px',
|
||||
},
|
||||
style: {
|
||||
color: '#fff',
|
||||
textDecoration: 'none !important',
|
||||
margin: '10px',
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
texts.top
|
||||
),
|
||||
$element(
|
||||
'p',
|
||||
{
|
||||
style: {
|
||||
color: '#fff',
|
||||
textDecoration: 'none !important',
|
||||
margin: '10px',
|
||||
},
|
||||
},
|
||||
texts.bottom
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
const toggleImage = function(element) {
|
||||
|
@ -219,9 +216,9 @@ Umi.Parsing = (function() {
|
|||
element.dataset.embed = '1';
|
||||
element.classList.add('markup__link--visited');
|
||||
|
||||
let html = $e({
|
||||
tag: 'img',
|
||||
attrs: {
|
||||
let html = $element(
|
||||
'img',
|
||||
{
|
||||
src: url,
|
||||
alt: url,
|
||||
style: {
|
||||
|
@ -234,7 +231,7 @@ Umi.Parsing = (function() {
|
|||
container.scrollIntoView({ inline: 'end' });
|
||||
},
|
||||
},
|
||||
});
|
||||
);
|
||||
|
||||
if(mami.settings.get('motivationalImages'))
|
||||
html = motivFrame(
|
||||
|
@ -256,16 +253,16 @@ Umi.Parsing = (function() {
|
|||
element.dataset.embed = '0';
|
||||
element.textContent = 'Embed';
|
||||
container.textContent = '';
|
||||
container.appendChild($e({
|
||||
tag: 'a',
|
||||
attrs: {
|
||||
container.appendChild($element(
|
||||
'a',
|
||||
{
|
||||
href: url,
|
||||
target: '_blank',
|
||||
rel: 'nofollow noreferrer noopener',
|
||||
className: 'markup__link',
|
||||
},
|
||||
child: url,
|
||||
}));
|
||||
url,
|
||||
));
|
||||
} else {
|
||||
container.title = 'audio';
|
||||
element.dataset.embed = '1';
|
||||
|
@ -273,9 +270,9 @@ Umi.Parsing = (function() {
|
|||
container.textContent = '';
|
||||
element.classList.add('markup__link--visited');
|
||||
|
||||
let media = $e({
|
||||
tag: 'audio',
|
||||
attrs: {
|
||||
let media = $element(
|
||||
'audio',
|
||||
{
|
||||
src: url,
|
||||
controls: true,
|
||||
onloadedmetadata: () => {
|
||||
|
@ -285,7 +282,7 @@ Umi.Parsing = (function() {
|
|||
media.play();
|
||||
},
|
||||
},
|
||||
});
|
||||
);
|
||||
|
||||
container.appendChild(media);
|
||||
}
|
||||
|
@ -300,25 +297,25 @@ Umi.Parsing = (function() {
|
|||
element.dataset.embed = '0';
|
||||
element.textContent = 'Embed';
|
||||
container.textContent = '';
|
||||
container.appendChild($e({
|
||||
tag: 'a',
|
||||
attrs: {
|
||||
container.appendChild($element(
|
||||
'a',
|
||||
{
|
||||
href: url,
|
||||
target: '_blank',
|
||||
rel: 'nofollow noreferrer noopener',
|
||||
className: 'markup__link',
|
||||
},
|
||||
child: url,
|
||||
}));
|
||||
url,
|
||||
));
|
||||
} else {
|
||||
container.title = 'video';
|
||||
element.dataset.embed = '1';
|
||||
element.textContent = 'Remove';
|
||||
element.classList.add('markup__link--visited');
|
||||
|
||||
let media = $e({
|
||||
tag: 'video',
|
||||
attrs: {
|
||||
let media = $element(
|
||||
'video',
|
||||
{
|
||||
src: url,
|
||||
controls: true,
|
||||
style: {
|
||||
|
@ -332,7 +329,7 @@ Umi.Parsing = (function() {
|
|||
media.play();
|
||||
},
|
||||
},
|
||||
});
|
||||
);
|
||||
|
||||
let html = media;
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include utility.js
|
||||
|
||||
const MamiSettingsBackup = function(settings) {
|
||||
const header = 'Mami Settings Export';
|
||||
const version = 1;
|
||||
|
@ -88,7 +86,7 @@ const MamiSettingsBackup = function(settings) {
|
|||
fileName = 'settings.mami';
|
||||
|
||||
const data = exportData();
|
||||
const html = $e('a', {
|
||||
const html = $element('a', {
|
||||
href: URL.createObjectURL(new Blob([data], { type: 'application/octet-stream' })),
|
||||
download: fileName,
|
||||
target: '_blank',
|
||||
|
@ -102,7 +100,7 @@ const MamiSettingsBackup = function(settings) {
|
|||
importFile: importFile,
|
||||
importUpload: (target) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const html = $e('input', {
|
||||
const html = $element('input', {
|
||||
type: 'file',
|
||||
accept: '.mami',
|
||||
style: { display: 'none' },
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include utility.js
|
||||
|
||||
const MamiSidebarActionCollapseAll = function() {
|
||||
// this should take a reference to the message container rather than just using $qa
|
||||
|
||||
|
@ -12,7 +10,7 @@ const MamiSidebarActionCollapseAll = function() {
|
|||
},
|
||||
|
||||
onclick: () => {
|
||||
const buttons = $qa('[data-embed="1"]');
|
||||
const buttons = $queryAll('[data-embed="1"]');
|
||||
for(const button of buttons)
|
||||
button.click();
|
||||
},
|
||||
|
|
|
@ -191,7 +191,7 @@ const MamiSidebarPanelSettings = function(settings, msgBox) {
|
|||
|
||||
const updateSelectOptions = () => {
|
||||
const options = setting.options();
|
||||
$rc(input);
|
||||
$removeChildren(input);
|
||||
for(const name in options)
|
||||
input.appendChild(<option class={`setting__style setting__style--${setting.name}-${name}`} value={name}>
|
||||
{options[name]}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include utility.js
|
||||
|
||||
const MamiSidebarPanelUploadsEntry = function(fileInfo) {
|
||||
const options = new Map;
|
||||
let uploadInfo;
|
||||
|
@ -164,7 +162,7 @@ const MamiSidebarPanelUploads = function() {
|
|||
return;
|
||||
|
||||
html.removeChild(entry.element);
|
||||
$ari(entries, entry);
|
||||
$arrayRemoveValue(entries, entry);
|
||||
},
|
||||
|
||||
addOption: option => {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include animate.js
|
||||
#include users.js
|
||||
#include utility.js
|
||||
|
||||
const MamiSidebarPanelUsersEntry = function(info) {
|
||||
const id = info.id;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include utility.js
|
||||
|
||||
const MamiSoundManager = function(context) {
|
||||
const probablySupported = [];
|
||||
const maybeSupported = [];
|
||||
|
@ -12,7 +10,7 @@ const MamiSoundManager = function(context) {
|
|||
};
|
||||
|
||||
(() => {
|
||||
const elem = $e('audio');
|
||||
const elem = $element('audio');
|
||||
for(const name in formats) {
|
||||
const format = formats[name];
|
||||
const support = elem.canPlayType(format);
|
||||
|
|
|
@ -130,7 +130,7 @@ const MamiSoundTest = function(settings, audio, manager, library, clickPos) {
|
|||
console.error(ex);
|
||||
state.textContent = `Error: ${ex}`;
|
||||
} finally {
|
||||
$ari(sources, source);
|
||||
$arrayRemoveValue(sources, source);
|
||||
await MamiSleep(2000);
|
||||
nowPlaying.removeChild(player);
|
||||
}
|
||||
|
|
|
@ -311,7 +311,7 @@ const UmiThemeApply = function(theme) {
|
|||
|
||||
if(theme.colours) {
|
||||
if(typeof theme.colours['main-background'] === 'number') {
|
||||
const themeColour = $q('meta[name="theme-color"]');
|
||||
const themeColour = $query('meta[name="theme-color"]');
|
||||
if(themeColour instanceof Element)
|
||||
themeColour.content = MamiColour.hex(theme.colours['main-background']);
|
||||
}
|
||||
|
|
|
@ -1,25 +1,12 @@
|
|||
#include utility.js
|
||||
#include ui/chat-message-list.js
|
||||
|
||||
Umi.UI.ChatInterface = function(chatForm) {
|
||||
const messages = new Umi.UI.ChatMessageList;
|
||||
|
||||
const html = $e({
|
||||
attrs: {
|
||||
className: 'main',
|
||||
},
|
||||
child: [
|
||||
messages,
|
||||
chatForm,
|
||||
],
|
||||
});
|
||||
const element = $element('div', { className: 'main' }, messages, chatForm);
|
||||
|
||||
return {
|
||||
getMessageList: function() {
|
||||
return messages;
|
||||
},
|
||||
getElement: function() {
|
||||
return html;
|
||||
},
|
||||
get messageList() { return messages; },
|
||||
get element() { return element; },
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,27 +1,12 @@
|
|||
#include utility.js
|
||||
#include ui/chat-interface.js
|
||||
|
||||
// this needs revising at some point but will suffice for now
|
||||
Umi.UI.ChatLayout = function(chatForm, sideBar) {
|
||||
const main = new Umi.UI.ChatInterface(chatForm);
|
||||
|
||||
const html = $e({
|
||||
attrs: {
|
||||
id: 'umi-chat',
|
||||
className: 'umi',
|
||||
},
|
||||
child: [
|
||||
main,
|
||||
sideBar,
|
||||
],
|
||||
});
|
||||
const element = $element('div', { id: 'umi-chat', className: 'umi' }, main, sideBar);
|
||||
|
||||
return {
|
||||
getInterface: function() {
|
||||
return main;
|
||||
},
|
||||
getElement: function() {
|
||||
return html;
|
||||
},
|
||||
get interface() { return main; },
|
||||
get element() { return element; },
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,16 +1,7 @@
|
|||
#include utility.js
|
||||
|
||||
Umi.UI.ChatMessageList = function() {
|
||||
const html = $e({
|
||||
attrs: {
|
||||
id: 'umi-messages',
|
||||
className: 'chat',
|
||||
},
|
||||
});
|
||||
const element = $element('div', { id: 'umi-messages', className: 'chat' });
|
||||
|
||||
return {
|
||||
getElement: function() {
|
||||
return html;
|
||||
},
|
||||
get element() { return element; },
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include emotes.js
|
||||
#include utility.js
|
||||
|
||||
Umi.UI.Emoticons = (function() {
|
||||
return {
|
||||
|
@ -7,13 +6,7 @@ Umi.UI.Emoticons = (function() {
|
|||
let inner = element.innerHTML;
|
||||
|
||||
MamiEmotes.forEach(author?.perms?.rank ?? 0, function(emote) {
|
||||
const image = $e({
|
||||
tag: 'img',
|
||||
attrs: {
|
||||
className: 'emoticon',
|
||||
src: emote.url,
|
||||
},
|
||||
});
|
||||
const image = $element('img', { className: 'emoticon', src: emote.url });
|
||||
|
||||
for (const i in emote.strings) {
|
||||
const trigger = ':' + emote.strings[i] + ':',
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include utility.js
|
||||
|
||||
Umi.UI.LoadingOverlay = function(icon, header, message) {
|
||||
const icons = {
|
||||
'spinner': 'fas fa-3x fa-fw fa-spinner fa-pulse',
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include txtrigs.js
|
||||
#include url.js
|
||||
#include users.js
|
||||
#include utility.js
|
||||
#include weeb.js
|
||||
#include sound/umisound.js
|
||||
#include ui/emotes.js
|
||||
|
@ -97,7 +96,7 @@ Umi.UI.Messages = (function() {
|
|||
Add: function(msg) {
|
||||
const elementId = `message-${msg.id}`;
|
||||
|
||||
if(msg.id !== '' && $i(elementId))
|
||||
if(msg.id !== '' && $id(elementId))
|
||||
return;
|
||||
|
||||
let isTiny = false;
|
||||
|
@ -254,8 +253,8 @@ Umi.UI.Messages = (function() {
|
|||
}
|
||||
|
||||
if(mami.settings.get('weeaboo')) {
|
||||
eUser.appendChild($t(Weeaboo.getNameSuffix(msgAuthor)));
|
||||
eText.appendChild($t(Weeaboo.getTextSuffix(msgAuthor)));
|
||||
eUser.appendChild($text(Weeaboo.getNameSuffix(msgAuthor)));
|
||||
eText.appendChild($text(Weeaboo.getTextSuffix(msgAuthor)));
|
||||
|
||||
const kaomoji = Weeaboo.getRandomKaomoji(true, msg);
|
||||
if(kaomoji)
|
||||
|
@ -269,7 +268,7 @@ Umi.UI.Messages = (function() {
|
|||
else
|
||||
eAvatar.classList.add('message__avatar--disabled');
|
||||
|
||||
const msgsList = $i('umi-messages');
|
||||
const msgsList = $id('umi-messages');
|
||||
|
||||
let insertAfter = msgsList.lastElementChild;
|
||||
if(insertAfter instanceof Element) {
|
||||
|
@ -372,11 +371,11 @@ Umi.UI.Messages = (function() {
|
|||
mami.globalEvents.dispatch('umi:ui:message_add', { element: eBase });
|
||||
},
|
||||
IsScrolledToBottom: () => {
|
||||
const msgsList = $i('umi-messages');
|
||||
const msgsList = $id('umi-messages');
|
||||
return msgsList.scrollTop === (msgsList.scrollHeight - msgsList.offsetHeight);
|
||||
},
|
||||
ScrollIfNeeded: (offsetOrForce = 0) => {
|
||||
const msgsList = $i('umi-messages');
|
||||
const msgsList = $id('umi-messages');
|
||||
if(!(msgsList instanceof Element))
|
||||
return;
|
||||
|
||||
|
@ -397,7 +396,7 @@ Umi.UI.Messages = (function() {
|
|||
|
||||
focusChannelName = channel;
|
||||
|
||||
const root = $i('umi-messages');
|
||||
const root = $id('umi-messages');
|
||||
for(const elem of root.children)
|
||||
elem.classList.toggle('hidden', elem.dataset.channel !== undefined && elem.dataset.channel !== focusChannelName);
|
||||
|
||||
|
@ -409,7 +408,7 @@ Umi.UI.Messages = (function() {
|
|||
if(typeof retain !== 'number')
|
||||
return;
|
||||
|
||||
const root = $i('umi-messages');
|
||||
const root = $id('umi-messages');
|
||||
|
||||
// remove messages
|
||||
if(root.childElementCount > retain)
|
||||
|
@ -419,7 +418,7 @@ Umi.UI.Messages = (function() {
|
|||
if(!elem.dataset.channel || elem.classList.contains('hidden') || --retain > 0)
|
||||
continue;
|
||||
|
||||
$r(elem);
|
||||
elem.remove();
|
||||
}
|
||||
|
||||
// fix author display
|
||||
|
@ -441,7 +440,7 @@ Umi.UI.Messages = (function() {
|
|||
if(msgId === '')
|
||||
return;
|
||||
|
||||
const elem = $i(`message-${msgId}`);
|
||||
const elem = $id(`message-${msgId}`);
|
||||
if(!(elem instanceof Element))
|
||||
return;
|
||||
|
||||
|
@ -449,7 +448,7 @@ Umi.UI.Messages = (function() {
|
|||
if(elem.nextElementSibling && elem.nextElementSibling.dataset.author === elem.dataset.author)
|
||||
elem.nextElementSibling.classList.add('message--first');
|
||||
|
||||
$r(elem);
|
||||
elem.remove();
|
||||
},
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const MamiRandomInt = (min, max) => {
|
||||
const $rngi = (min, max) => {
|
||||
let ret = 0;
|
||||
const range = max - min;
|
||||
|
||||
|
@ -21,18 +21,18 @@ const MamiRandomInt = (min, max) => {
|
|||
ret &= mask;
|
||||
|
||||
if(ret >= range)
|
||||
return MamiRandomInt(min, max);
|
||||
return $rngi(min, max);
|
||||
|
||||
return min + ret;
|
||||
};
|
||||
|
||||
const MamiUniqueStr = (() => {
|
||||
const $rngs = (() => {
|
||||
const chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789';
|
||||
|
||||
return length => {
|
||||
let str = '';
|
||||
for(let i = 0; i < length; ++i)
|
||||
str += chars[MamiRandomInt(0, chars.length)];
|
||||
str += chars[$rngi(0, chars.length)];
|
||||
return str;
|
||||
};
|
||||
})();
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
const $i = document.getElementById.bind(document);
|
||||
const $c = document.getElementsByClassName.bind(document);
|
||||
const $q = document.querySelector.bind(document);
|
||||
const $qa = document.querySelectorAll.bind(document);
|
||||
const $t = document.createTextNode.bind(document);
|
||||
|
||||
const $r = function(element) {
|
||||
if(element && element.parentNode)
|
||||
element.parentNode.removeChild(element);
|
||||
};
|
||||
|
||||
const $ri = function(name) {
|
||||
$r($i(name));
|
||||
};
|
||||
|
||||
const $rq = function(query) {
|
||||
$r($q(query));
|
||||
};
|
||||
|
||||
const $ib = function(ref, elem) {
|
||||
ref.parentNode.insertBefore(elem, ref);
|
||||
};
|
||||
|
||||
const $rc = function(element) {
|
||||
while(element.lastChild)
|
||||
element.removeChild(element.lastChild);
|
||||
};
|
||||
|
||||
const $e = function(info, attrs, child, created) {
|
||||
info = info || {};
|
||||
|
||||
if(typeof info === 'string') {
|
||||
info = {tag: info};
|
||||
if(attrs)
|
||||
info.attrs = attrs;
|
||||
if(child)
|
||||
info.child = child;
|
||||
if(created)
|
||||
info.created = created;
|
||||
}
|
||||
|
||||
const elem = document.createElement(info.tag || 'div');
|
||||
|
||||
if(info.attrs) {
|
||||
const attrs = info.attrs;
|
||||
|
||||
for(let key in attrs) {
|
||||
const attr = attrs[key];
|
||||
if(attr === undefined || attr === null)
|
||||
continue;
|
||||
|
||||
switch(typeof attr) {
|
||||
case 'function':
|
||||
if(key.substring(0, 2) === 'on')
|
||||
key = key.substring(2).toLowerCase();
|
||||
elem.addEventListener(key, attr);
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
if(attr instanceof Array) {
|
||||
if(key === 'class')
|
||||
key = 'classList';
|
||||
|
||||
const prop = elem[key];
|
||||
let addFunc = null;
|
||||
|
||||
if(prop instanceof Array)
|
||||
addFunc = prop.push.bind(prop);
|
||||
else if(prop instanceof DOMTokenList)
|
||||
addFunc = prop.add.bind(prop);
|
||||
|
||||
if(addFunc !== null) {
|
||||
for(let j = 0; j < attr.length; ++j)
|
||||
addFunc(attr[j]);
|
||||
} else {
|
||||
if(key === 'classList')
|
||||
key = 'class';
|
||||
elem.setAttribute(key, attr.toString());
|
||||
}
|
||||
} else {
|
||||
for(const attrKey in attr)
|
||||
elem[key][attrKey] = attr[attrKey];
|
||||
}
|
||||
break;
|
||||
|
||||
case 'boolean':
|
||||
if(attr)
|
||||
elem.setAttribute(key, '');
|
||||
break;
|
||||
|
||||
default:
|
||||
if(key === 'className')
|
||||
key = 'class';
|
||||
elem.setAttribute(key, attr.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(info.child) {
|
||||
let children = info.child;
|
||||
|
||||
if(!Array.isArray(children))
|
||||
children = [children];
|
||||
|
||||
for(const child of children) {
|
||||
switch(typeof child) {
|
||||
case 'string':
|
||||
elem.appendChild($t(child));
|
||||
break;
|
||||
|
||||
case 'object':
|
||||
if(child instanceof Element) {
|
||||
elem.appendChild(child);
|
||||
} else if('element' in child) {
|
||||
const childElem = child.element;
|
||||
if(childElem instanceof Element)
|
||||
elem.appendChild(childElem);
|
||||
else
|
||||
elem.appendChild($e(child));
|
||||
} else if('getElement' in child) {
|
||||
const childElem = child.getElement();
|
||||
if(childElem instanceof Element)
|
||||
elem.appendChild(childElem);
|
||||
else
|
||||
elem.appendChild($e(child));
|
||||
} else {
|
||||
elem.appendChild($e(child));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
elem.appendChild($t(child.toString()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(info.created)
|
||||
info.created(elem);
|
||||
|
||||
return elem;
|
||||
};
|
||||
const $er = (type, props, ...children) => $e({ tag: type, attrs: props, child: children });
|
||||
|
||||
const $ar = function(array, index) {
|
||||
array.splice(index, 1);
|
||||
};
|
||||
const $ari = function(array, item) {
|
||||
let index;
|
||||
while(array.length > 0 && (index = array.indexOf(item)) >= 0)
|
||||
$ar(array, index);
|
||||
};
|
||||
const $arf = function(array, predicate) {
|
||||
let index;
|
||||
while(array.length > 0 && (index = array.findIndex(predicate)) >= 0)
|
||||
$ar(array, index);
|
||||
};
|
||||
|
||||
const $as = function(array) {
|
||||
if(array.length < 2)
|
||||
return;
|
||||
|
||||
for(let i = array.length - 1; i > 0; --i) {
|
||||
let j = Math.floor(Math.random() * (i + 1)),
|
||||
tmp = array[i];
|
||||
array[i] = array[j];
|
||||
array[j] = tmp;
|
||||
}
|
||||
};
|
|
@ -1,6 +1,5 @@
|
|||
#include common.js
|
||||
#include rng.js
|
||||
#include xhr.js
|
||||
|
||||
const Weeaboo = (function() {
|
||||
let kaomoji = [];
|
||||
|
@ -16,7 +15,7 @@ const Weeaboo = (function() {
|
|||
if(kaomoji.length > 0)
|
||||
return;
|
||||
|
||||
$x.get(futami.get('kaomoji'))
|
||||
$xhr.get(futami.get('kaomoji'))
|
||||
.then(resp => kaomoji = resp.text.split("\n"));
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const $x = (function() {
|
||||
const $xhr = (function() {
|
||||
const send = function(method, url, options, body) {
|
||||
if(options === undefined)
|
||||
options = {};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue