mami/src/mami.js/ui/settings.jsx

554 lines
19 KiB
JavaScript

#include animate.js
#include common.js
#include emotes.js
#include utility.js
#include youare.jsx
#include settings/backup.js
#include ui/emotes.js
#include ui/menus.js
#include ui/view.js
Umi.UI.Settings = (function() {
const items = [
{
name: 'interface',
title: 'Interface',
items: [
{
name: 'style',
title: 'Style',
type: 'select',
options: () => Umi.UI.View.AccentColours,
},
{
name: 'compactView',
title: 'Compact view',
type: 'checkbox',
},
{
name: 'autoScroll',
title: 'Scroll to latest message',
type: 'checkbox',
},
{
name: 'closeTabConfirm',
title: 'Confirm tab close',
type: 'checkbox',
},
{
name: 'showChannelList',
title: 'Show channel list',
type: 'checkbox',
},
{
name: 'fancyInfo',
title: 'Fancy server messages',
type: 'checkbox',
},
{
name: 'autoCloseUserContext',
title: 'Auto-close user menus',
type: 'checkbox',
},
],
},
{
name: 'text',
title: 'Text',
items: [
{
name: 'enableParser',
title: 'Parse markup',
type: 'checkbox',
},
{
name: 'enableEmoticons',
title: 'Parse emoticons',
type: 'checkbox',
},
{
name: 'autoParseUrls',
title: 'Auto detect links',
type: 'checkbox',
},
{
name: 'preventOverflow',
title: 'Prevent overflow',
type: 'checkbox',
},
{
name: 'expandTextBox',
title: 'Grow input box',
type: 'checkbox',
},
{
name: 'eepromAutoInsert',
title: 'Auto-insert uploads',
type: 'checkbox',
},
{
name: 'autoEmbedV1',
title: 'Auto-embed media',
type: 'checkbox',
},
],
},
{
name: 'notification',
title: 'Notification',
items: [
{
name: 'flashTitle',
title: 'Strobe title on new message',
type: 'checkbox',
},
{
name: 'showServerMsgInTitle',
title: 'Show server message in title',
type: 'checkbox',
},
{
name: 'enableNotifications',
title: 'Show notifications',
type: 'checkbox',
},
{
name: 'notificationShowMessage',
title: 'Show contents of message',
type: 'checkbox',
},
{
name: 'notificationTriggers',
title: 'Triggers',
type: 'text',
},
],
},
{
name: 'sounds',
title: 'Sound',
items: [
{
name: 'soundEnable',
title: 'Enable sound',
type: 'checkbox',
},
{
name: 'soundPack',
title: 'Sound pack',
type: 'select',
options: () => {
const packs = {};
mami.getSoundPacks().forEachPack(function(pack) {
packs[pack.getName()] = pack.getTitle();
});
return packs;
},
},
{
name: 'soundVolume',
title: 'Sound volume',
type: 'range',
},
{
name: 'soundEnableJoin',
title: 'Play join sound',
type: 'checkbox',
},
{
name: 'soundEnableLeave',
title: 'Play leave sound',
type: 'checkbox',
},
{
name: 'soundEnableError',
title: 'Play error sound',
type: 'checkbox',
},
{
name: 'soundEnableServer',
title: 'Play server message sound',
type: 'checkbox',
},
{
name: 'soundEnableIncoming',
title: 'Play receive message sound',
type: 'checkbox',
},
{
name: 'onlySoundOnMention',
title: 'Only play receive sound on mention',
type: 'checkbox',
},
{
name: 'soundEnableOutgoing',
title: 'Play send message sound',
type: 'checkbox',
},
{
name: 'soundEnablePrivate',
title: 'Play private message sound',
type: 'checkbox',
},
{
name: 'soundEnableForceLeave',
title: 'Play kick sound',
type: 'checkbox',
},
{
name: 'minecraft',
title: 'Minecraft',
type: 'select',
options: () => {
return {
'no': 'No Minecraft',
'yes': 'Yes Minecraft',
'old': 'Old Minecraft',
};
},
},
{
name: 'playSoundOnConnect',
title: 'Play join sound on connect',
type: 'checkbox',
},
{
name: 'windowsLiveMessenger',
title: 'Windows Live Messenger',
type: 'checkbox',
},
{
name: 'seinfeld',
title: 'Seinfeld',
type: 'checkbox',
},
],
},
{
name: 'misc',
title: 'Misc',
items: [
{
name: 'playJokeSounds',
title: 'Run joke triggers',
type: 'checkbox',
},
{
name: 'weeaboo',
title: 'Weeaboo',
type: 'checkbox',
},
{
name: 'motivationalImages',
title: 'Make images motivational',
type: 'checkbox',
},
{
name: 'motivationalVideos',
title: 'Make videos motivational',
type: 'checkbox',
},
{
name: 'osuKeysV2',
title: 'osu! keyboard sounds',
type: 'select',
options: () => {
return {
'no': 'Off',
'yes': 'On',
'rng': 'On, random pitch',
};
},
},
{
name: 'explosionRadius',
title: 'Messages to keep on clear',
type: 'number',
},
{
title: 'Reload emoticons',
type: 'button',
invoke: button => {
const emotes = futami.get('emotes');
setTimeout(() => {
button.disabled = true;
futami.getJson('emotes', true)
.then(emotes => {
MamiEmotes.clear();
MamiEmotes.loadLegacy(emotes);
})
.finally(() => {
Umi.UI.Emoticons.Init();
button.disabled = false;
});
}, 200);
},
},
{
title: 'Reload joke triggers',
type: 'button',
invoke: button => {
button.disabled = true;
const triggers = mami.getTextTriggers();
triggers.clearTriggers();
if(mami.getSettings().get('playJokeSounds'))
futami.getJson('texttriggers', true)
.then(trigInfos => triggers.addTriggers(trigInfos))
.finally(() => button.disabled = false);
},
},
{
title: 'Open compatibility client',
type: 'button',
invoke: () => {
const meow = $e('a', { href: window.AMI_URL, target: '_blank', style: { display: 'none' } });
document.body.appendChild(meow);
meow.click();
$r(meow);
},
},
],
},
{
name: 'settings',
title: 'Settings',
items: [
{
title: 'Import settings',
type: 'button',
invoke: () => {
if(!confirm('Your current settings will be replaced with the ones in the export. Are you sure you want to continue?'))
return;
(new MamiSettingsBackup(mami.getSettings())).importUpload(document.body);
},
},
{
title: 'Export settings',
type: 'button',
invoke: () => {
const user = Umi.User.getCurrentUser();
let fileName;
if(user !== null)
fileName = `${user.getName()}'s settings.mami`;
(new MamiSettingsBackup(mami.getSettings())).exportDownload(document.body, fileName);
},
},
{
title: 'Reset settings',
type: 'button',
invoke: () => {
if(!confirm('This will reset all your settings to their defaults values. Are you sure you want to do this?'))
return;
mami.getSettings().clear();
},
},
],
},
{
name: 'debug',
title: 'Debug',
collapse: true,
warning: "Only touch these settings if you're ABSOLUTELY sure you know what you're doing, you're on your own if you break something.",
items: [
{
name: 'dumpPackets',
title: 'Dump packets to console',
type: 'checkbox',
},
{
name: 'neverUseWorker',
title: 'Never use Worker for connection',
type: 'checkbox',
confirm: "If you're here it likely means that you mistakenly believe that your browser doesn't suck. You may go ahead but if disabling this causes any annoyances for other users you will be expunged.",
},
{
name: 'forceUseWorker',
title: 'Always use Worker for connection',
type: 'checkbox',
},
{
name: 'marqueeAllNames',
title: 'Apply marquee on everyone',
type: 'checkbox',
},
{
name: 'tmpDisableOldThemeSys',
title: 'Disable Old Theme System',
type: 'checkbox',
},
{
name: 'tmpSkipDomainPopUpThing',
title: 'Skip domain pop up thing',
type: 'checkbox',
},
{
title: 'You are an idiot!',
type: 'button',
invoke: async button => {
button.disabled = true;
await (new MamiYouAreAnIdiot()).pushOn(mami.getViews());
button.disabled = false;
},
},
],
}
];
const createCopyright = function() {
return <div class="mami-copyright">
<a href="//patchii.net/flashii/mami" target="_blank">Mami</a> © <a href="//flash.moe" target="_blank">flash.moe</a><br/>
<a href="//railgun.sh/sockchat" target="_blank">Sock Chat documentation</a>
</div>;
};
const createSetting = function(display) {
const settings = mami.getSettings();
let setting;
if('name' in display)
setting = settings.info(display.name);
let input = display.type === 'select'
? <select class="setting__input"/>
: <input type={display.type} class="setting__input"/>;
if(display.disabled === true)
input.disabled = true;
if(display.type === 'select') {
const options = display.options();
for(const name in options)
input.appendChild(<option class={['setting__style', `setting__style--${display.name}-${name}`]} value={name}>
{options[name]}
</option>);
} else if(display.type === 'button') {
input.value = display.title;
input.addEventListener('click', () => display.invoke(input));
}
if(setting !== undefined) {
if(!input.disabled && setting.immutable)
input.disabled = true;
if(display.type === 'checkbox') {
settings.watch(setting.name, v => input.checked = v);
input.addEventListener('change', () => {
if(display.confirm !== undefined && input.checked !== setting.fallback && !confirm(display.confirm)) {
input.checked = setting.fallback;
return;
}
settings.toggle(setting.name);
});
} else {
settings.watch(setting.name, v => input.value = v);
input.addEventListener('change', () => settings.set(setting.name, input.value));
}
}
let label = input;
if(display.type === 'checkbox') {
label = <label class="setting__label">
{input}
<div>{display.title}</div>
</label>;
} else if(display.type === 'button') {
label = <label class="setting__label">{input}</label>;
} else {
label = <label class="setting__label">
<div>{display.title}</div>
{input}
</label>;
}
return <div class={['setting__container', `setting__container--${display.type}`]}>{label}</div>;
};
const createCategory = function(category) {
const catHeader = <div class={['setting__category-title', `setting__category-title--${category.name}`]} style={{ cursor: 'pointer' }}>{category.title}</div>;
const catBody = <div class={['setting__category', `setting__category--${category.name}`]} style={{ overflow: 'hidden' }}/>;
const catContainer = <div>{catHeader}{catBody}</div>;
catHeader.onclick = () => {
if(catContainer.dataset.mamiAnimRun === 'yes')
return;
catContainer.dataset.mamiAnimRun = 'yes';
let start, update, end, height;
if(catContainer.dataset.mamiIsClosed === 'yes') {
catContainer.dataset.mamiIsClosed = 'no';
start = () => {
const curHeight = catBody.style.height;
catBody.style.height = null;
height = catBody.clientHeight;
catBody.style.height = curHeight;
};
update = t => {
catBody.style.height = `${height * t}px`;
};
end = () => {
catBody.style.height = null;
catContainer.dataset.mamiAnimRun = 'no';
};
} else {
catContainer.dataset.mamiIsClosed = 'yes';
start = () => {
height = catBody.clientHeight;
};
update = t => {
catBody.style.height = `${height - (height * t)}px`;
};
end = () => {
catBody.style.height = '0';
catContainer.dataset.mamiAnimRun = 'no';
};
}
// todo: actually make cancellable
MamiAnimate({
duration: 500,
easing: 'outExpo',
start: start,
update: update,
end: end,
});
};
if(category.warning)
catBody.appendChild(<div style={{ fontSize: '.9em', lineHeight: '1.4em', margin: '5px', padding: '5px', backgroundColor: 'darkred', border: '2px solid red', borderRadius: '5px' }}>{category.warning}</div>);
if(category.items)
for(const item of category.items)
catBody.appendChild(createSetting(item));
return catContainer;
};
return {
Init: function() {
const html = Umi.UI.Menus.Get('settings');
$rc(html);
for(const category of items) {
const elem = createCategory(category);
html.appendChild(elem);
// only a little bit of hacking, stan
if(category.collapse)
elem.firstChild.click();
}
html.appendChild(createCopyright());
},
};
})();