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