Replaced window.alert and window.confirm with a custom dialog implementation.
This commit is contained in:
parent
1dcddffc03
commit
36e14399d8
10 changed files with 429 additions and 45 deletions
76
src/mami.css/controls/msgbox.css
Normal file
76
src/mami.css/controls/msgbox.css
Normal file
|
@ -0,0 +1,76 @@
|
|||
.msgbox-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: #1118;
|
||||
color: #fff;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
backdrop-filter: blur(2px);
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
grid-template-columns: 340px;
|
||||
}
|
||||
|
||||
.msgbox-dialog {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
font-family: Verdana, Geneva, Arial, Helvetica, sans-serif;
|
||||
font-size: .8em;
|
||||
line-height: 1.4em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: #444d;
|
||||
border: 1px solid #5554;
|
||||
backdrop-filter: blur(2px);
|
||||
filter: drop-shadow(0 6px 1em #000);
|
||||
}
|
||||
|
||||
.msgbox-dialog-body {
|
||||
margin: 6px;
|
||||
}
|
||||
.msgbox-dialog-line {
|
||||
margin: 6px;
|
||||
}
|
||||
|
||||
.msgbox-dialog-buttons {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
margin: 2px;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
.msgbox-dialog-buttons-many {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.msgbox-dialog-button {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
width: 100%;
|
||||
display: block;
|
||||
border: 0;
|
||||
background: #555d;
|
||||
border: 1px solid #6664;
|
||||
color: inherit;
|
||||
padding: 7px 4px 6px;
|
||||
transition: background .1s, border-color .1s;
|
||||
}
|
||||
.msgbox-dialog-button:focus {
|
||||
outline: 1px solid #ccc;
|
||||
}
|
||||
.msgbox-dialog-button:focus,
|
||||
.msgbox-dialog-button:hover {
|
||||
background: #666d;
|
||||
border-color: #7774;
|
||||
}
|
||||
.msgbox-dialog-button:active {
|
||||
background: #5a5a5add;
|
||||
border-color: #6a6a6a44;
|
||||
}
|
||||
.msgbox-dialog-button-primary {
|
||||
font-weight: 700;
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
@include __animations.css;
|
||||
@include _main.css;
|
||||
|
||||
@include views.css;
|
||||
@include controls/msgbox.css;
|
||||
@include controls/views.css;
|
||||
|
||||
@include baka.css;
|
||||
@include ping.css;
|
||||
|
|
|
@ -15,6 +15,7 @@ const MamiContext = function(globalEventTarget, eventTarget) {
|
|||
let isUnloading = false;
|
||||
|
||||
let settings;
|
||||
let msgbox;
|
||||
let views;
|
||||
let sound;
|
||||
let textTriggers;
|
||||
|
@ -40,6 +41,15 @@ const MamiContext = function(globalEventTarget, eventTarget) {
|
|||
settings = value;
|
||||
},
|
||||
|
||||
get msgbox() { return msgbox; },
|
||||
set msgbox(value) {
|
||||
if(msgbox !== undefined)
|
||||
throw 'msgbox is already defined';
|
||||
if(typeof value !== 'object' || value === null)
|
||||
throw 'msgbox must be a non-null object';
|
||||
msgbox = value;
|
||||
},
|
||||
|
||||
get views() { return views; },
|
||||
set views(value) {
|
||||
if(views !== undefined)
|
||||
|
|
262
src/mami.js/controls/msgbox.jsx
Normal file
262
src/mami.js/controls/msgbox.jsx
Normal file
|
@ -0,0 +1,262 @@
|
|||
#include animate.js
|
||||
#include args.js
|
||||
#include utility.js
|
||||
|
||||
const MamiMessageBoxContainer = function() {
|
||||
const container = <div class="msgbox-container"/>;
|
||||
|
||||
return {
|
||||
getElement: () => container,
|
||||
show: async dialog => {
|
||||
if(typeof dialog !== 'object' || dialog === null)
|
||||
throw 'dialog must be a non-null object';
|
||||
|
||||
try {
|
||||
return await dialog.show(container);
|
||||
} finally {
|
||||
dialog.dismiss();
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const MamiMessageBoxDialog = function(info) {
|
||||
const defaultButtons = [
|
||||
{ name: 'ok', text: 'OK', primary: true, reject: false },
|
||||
{ name: 'yes', text: 'Yes', primary: true, reject: false },
|
||||
{ name: 'no', text: 'No', reject: true },
|
||||
{ name: 'cancel', text: 'Cancel', reject: true },
|
||||
];
|
||||
|
||||
let showResolve, showReject;
|
||||
|
||||
const doResolve = (...args) => {
|
||||
if(typeof showResolve !== 'function')
|
||||
return;
|
||||
|
||||
showReject = undefined;
|
||||
showResolve(...args);
|
||||
};
|
||||
const doReject = (...args) => {
|
||||
if(typeof showReject !== 'function')
|
||||
return;
|
||||
|
||||
showResolve = undefined;
|
||||
showReject(...args);
|
||||
};
|
||||
|
||||
const dialog = <form class="msgbox-dialog"/>;
|
||||
|
||||
const body = <div class="msgbox-dialog-body"/>;
|
||||
dialog.appendChild(body);
|
||||
|
||||
if(info.body !== undefined) {
|
||||
if(Array.isArray(info.body))
|
||||
for(const line of info.body)
|
||||
body.appendChild(<p class="msgbox-dialog-line">{line}</p>);
|
||||
else
|
||||
body.appendChild(<p class="msgbox-dialog-line">{info.body}</p>);
|
||||
}
|
||||
|
||||
const buttons = <div class="msgbox-dialog-buttons"/>;
|
||||
const buttonActions = {};
|
||||
dialog.appendChild(buttons);
|
||||
|
||||
let primaryButton;
|
||||
const createButton = button => {
|
||||
if(button.name === undefined) {
|
||||
console.error('No name specified for dialog button. Skipping...');
|
||||
return;
|
||||
}
|
||||
|
||||
const buttonName = button.name.toString();
|
||||
if(buttons.querySelector(`[name="${buttonName}"]`) !== null) {
|
||||
console.error('A duplicate button name was attempted to be registered. Skipping...');
|
||||
return;
|
||||
}
|
||||
|
||||
const elem = <button class="msgbox-dialog-button" name={buttonName} data-action={button.reject ? 'reject' : 'resolve'}>{button.text ?? buttonName ?? ''}</button>;
|
||||
buttons.appendChild(elem);
|
||||
|
||||
if(button.primary) {
|
||||
primaryButton = elem;
|
||||
elem.classList.add('msgbox-dialog-button-primary');
|
||||
}
|
||||
|
||||
if(typeof button.action === 'function')
|
||||
buttonActions[buttonName] = button.action;
|
||||
};
|
||||
|
||||
for(const item of defaultButtons)
|
||||
if(item.name in info) {
|
||||
const button = typeof info[item.name] === 'object' && info[item.name] !== null ? info[item.name] : {};
|
||||
|
||||
button.name = item.name;
|
||||
button.reject = item.reject;
|
||||
if(button.primary === undefined)
|
||||
button.primary = item.primary;
|
||||
if(button.text === undefined)
|
||||
button.text = item.text;
|
||||
|
||||
createButton(button);
|
||||
}
|
||||
|
||||
if(Array.isArray(info.buttons))
|
||||
for(const button of info.buttons) {
|
||||
if(button.text === undefined)
|
||||
button.text = button.name;
|
||||
|
||||
createButton(button);
|
||||
}
|
||||
|
||||
if(buttons.childElementCount < 1)
|
||||
createButton({ name: 'dismiss', text: 'Dismiss', primary: true });
|
||||
|
||||
if(buttons.childElementCount > 2)
|
||||
buttons.classList.add('msgbox-dialog-buttons-many');
|
||||
|
||||
return {
|
||||
getElement: () => dialog,
|
||||
show: container => {
|
||||
return new Promise((resolve, reject) => {
|
||||
showResolve = resolve;
|
||||
showReject = reject;
|
||||
|
||||
dialog.addEventListener('submit', ev => {
|
||||
ev.preventDefault();
|
||||
|
||||
if(ev.submitter instanceof HTMLButtonElement) {
|
||||
const action = ev.submitter.dataset.action === 'resolve' ? doResolve : doReject;
|
||||
|
||||
let result;
|
||||
if(ev.submitter.name in buttonActions)
|
||||
result = buttonActions[ev.submitter.name]();
|
||||
|
||||
if(result instanceof Promise)
|
||||
result.then(result => { action(ev.submitter.name, result, true); })
|
||||
.catch(result => { action(ev.submitter.name, result, false); });
|
||||
else
|
||||
action(ev.submitter.name, result);
|
||||
} else doResolve();
|
||||
});
|
||||
|
||||
dialog.style.transform = 'scale(0)';
|
||||
container.appendChild(dialog);
|
||||
|
||||
if(primaryButton instanceof HTMLButtonElement)
|
||||
primaryButton.focus();
|
||||
|
||||
MamiAnimate({
|
||||
async: true,
|
||||
duration: 500,
|
||||
easing: 'outElasticHalf',
|
||||
update: t => {
|
||||
dialog.style.transform = `scale(${t})`;
|
||||
},
|
||||
end: () => {
|
||||
dialog.style.transform = null;
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
dismiss: async () => {
|
||||
await MamiAnimate({
|
||||
async: true,
|
||||
duration: 600,
|
||||
easing: 'outExpo',
|
||||
update: t => { dialog.style.opacity = 1 - t; },
|
||||
end: () => { dialog.style.opacity = '0'; },
|
||||
});
|
||||
|
||||
$r(dialog);
|
||||
},
|
||||
cancel: () => {
|
||||
doReject();
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const MamiMessageBoxControl = function(options) {
|
||||
options = MamiArguments.verify(options, [
|
||||
MamiArguments.type('views', 'object', undefined, true),
|
||||
]);
|
||||
|
||||
const views = options.views;
|
||||
const container = new MamiMessageBoxContainer;
|
||||
const queue = [];
|
||||
let currentDialog;
|
||||
|
||||
let processingQueue = false;
|
||||
const processQueue = async () => {
|
||||
if(processingQueue)
|
||||
return;
|
||||
|
||||
try {
|
||||
processingQueue = true;
|
||||
|
||||
let item;
|
||||
while((item = queue.shift()) !== undefined) {
|
||||
if(!processingQueue)
|
||||
break;
|
||||
|
||||
try {
|
||||
currentDialog = new MamiMessageBoxDialog(item.info);
|
||||
item.resolve(await container.show(currentDialog));
|
||||
} catch(ex) {
|
||||
item.reject(ex);
|
||||
} finally {
|
||||
currentDialog = undefined;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
processingQueue = false;
|
||||
}
|
||||
};
|
||||
|
||||
const raise = async () => {
|
||||
if(!views.isCurrent(container))
|
||||
views.raise(container, ctx => MamiAnimate({
|
||||
async: true,
|
||||
duration: 300,
|
||||
easing: 'outExpo',
|
||||
update: t => { ctx.toElem.style.opacity = t; },
|
||||
end: () => { ctx.toElem.style.opacity = null; },
|
||||
}));
|
||||
|
||||
if(!processingQueue)
|
||||
await processQueue();
|
||||
};
|
||||
|
||||
const dismiss = async () => {
|
||||
processingQueue = false;
|
||||
currentDialog?.cancel();
|
||||
|
||||
if(views.isCurrent(container))
|
||||
await views.pop(ctx => MamiAnimate({
|
||||
async: true,
|
||||
duration: 300,
|
||||
easing: 'outExpo',
|
||||
update: t => { ctx.fromElem.style.opacity = 1 - t; },
|
||||
end: t => { ctx.fromElem.style.opacity = '0'; },
|
||||
}));
|
||||
};
|
||||
|
||||
return {
|
||||
raise: raise,
|
||||
dismiss: dismiss,
|
||||
show: (info, priority) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const item = { info: info, resolve: resolve, reject: reject };
|
||||
|
||||
if(priority) queue.unshift(item);
|
||||
else queue.push(item);
|
||||
|
||||
let queueWasRunning = processingQueue;
|
||||
raise().finally(() => {
|
||||
if(!queueWasRunning)
|
||||
dismiss();
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
};
|
|
@ -53,7 +53,6 @@ const MamiViewsControl = function(options) {
|
|||
await elementInfo.onViewPush();
|
||||
|
||||
const element = extractElement(elementInfo);
|
||||
element.classList.toggle('hidden', false);
|
||||
element.classList.toggle('views-item', true);
|
||||
element.classList.toggle('views-background', false);
|
||||
|
||||
|
@ -80,8 +79,6 @@ const MamiViewsControl = function(options) {
|
|||
fromInfo: prevElemInfo,
|
||||
fromElem: prevElem,
|
||||
});
|
||||
|
||||
prevElem.classList.toggle('hidden', true);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -98,7 +95,6 @@ const MamiViewsControl = function(options) {
|
|||
const nextElemInfo = views[views.length - 1];
|
||||
const nextElem = extractElement(nextElemInfo);
|
||||
|
||||
nextElem.classList.toggle('hidden', false);
|
||||
nextElem.classList.toggle('views-background', false);
|
||||
|
||||
if(typeof nextElemInfo.onViewForeground === 'function')
|
||||
|
@ -115,8 +111,6 @@ const MamiViewsControl = function(options) {
|
|||
if(typeof elementInfo.onViewBackground === 'function')
|
||||
await elementInfo.onViewBackground();
|
||||
|
||||
element.classList.toggle('hidden', true);
|
||||
|
||||
if(targetBody.contains(element))
|
||||
targetBody.removeChild(element);
|
||||
|
||||
|
@ -135,9 +129,24 @@ const MamiViewsControl = function(options) {
|
|||
return views[views.length - 1];
|
||||
};
|
||||
|
||||
const raise = async (elementInfo, transition) => {
|
||||
if(typeof elementInfo !== 'object')
|
||||
throw 'elementInfo must be an object';
|
||||
|
||||
if(current() === elementInfo)
|
||||
return;
|
||||
|
||||
const index = views.indexOf(elementInfo);
|
||||
if(index >= 0)
|
||||
views.splice(index, 1);
|
||||
|
||||
return await push(elementInfo, transition);
|
||||
};
|
||||
|
||||
return {
|
||||
push: push,
|
||||
pop: pop,
|
||||
raise: raise,
|
||||
count: () => views.length,
|
||||
current: current,
|
||||
currentElement: () => {
|
||||
|
@ -147,6 +156,8 @@ const MamiViewsControl = function(options) {
|
|||
|
||||
return extractElement(currentInfo);
|
||||
},
|
||||
includes: elementInfo => views.includes(elementInfo),
|
||||
isCurrent: elementInfo => current() === elementInfo,
|
||||
unshift: async elementInfo => {
|
||||
if(views.length < 1)
|
||||
return await push(elementInfo, null);
|
||||
|
@ -159,7 +170,6 @@ const MamiViewsControl = function(options) {
|
|||
if(!views.includes(elementInfo))
|
||||
views.unshift(elementInfo);
|
||||
|
||||
element.classList.toggle('hidden', true);
|
||||
element.classList.toggle('views-item', true);
|
||||
element.classList.toggle('views-background', true);
|
||||
|
||||
|
@ -175,8 +185,6 @@ const MamiViewsControl = function(options) {
|
|||
const elementInfo = views.shift();
|
||||
const element = extractElement(elementInfo);
|
||||
|
||||
element.classList.toggle('hidden', false);
|
||||
|
||||
if(targetBody.contains(element))
|
||||
targetBody.removeChild(element);
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ window.Umi = { UI: {} };
|
|||
#include weeb.js
|
||||
#include worker.js
|
||||
#include audio/autoplay.js
|
||||
#include controls/msgbox.jsx
|
||||
#include controls/views.js
|
||||
#include eeprom/eeprom.js
|
||||
#include settings/backup.js
|
||||
|
@ -40,11 +41,11 @@ window.Umi = { UI: {} };
|
|||
const ctx = new MamiContext(eventTarget);
|
||||
Object.defineProperty(window, 'mami', { enumerable: true, value: ctx });
|
||||
|
||||
const views = new MamiViewsControl({ body: document.body });
|
||||
ctx.views = views;
|
||||
ctx.views = new MamiViewsControl({ body: document.body });
|
||||
ctx.msgbox = new MamiMessageBoxControl({ views: ctx.views });
|
||||
|
||||
const loadingOverlay = new Umi.UI.LoadingOverlay('spinner', 'Loading...');
|
||||
await views.push(loadingOverlay);
|
||||
await ctx.views.push(loadingOverlay);
|
||||
|
||||
loadingOverlay.setMessage('Loading environment...');
|
||||
try {
|
||||
|
@ -233,7 +234,7 @@ window.Umi = { UI: {} };
|
|||
|
||||
// should be dynamic when possible
|
||||
const layout = new Umi.UI.ChatLayout;
|
||||
await views.unshift(layout);
|
||||
await ctx.views.unshift(layout);
|
||||
|
||||
Umi.UI.View.AccentReload();
|
||||
Umi.UI.Hooks.AddHooks();
|
||||
|
@ -375,7 +376,7 @@ window.Umi = { UI: {} };
|
|||
|
||||
Umi.UI.Toggles.Add('clear', {
|
||||
'click': function() {
|
||||
if(confirm('ARE YOU SURE ABOUT THAT???')) {
|
||||
ctx.msgbox.show({ body: 'ARE YOU SURE ABOUT THAT???', yes: true, no: true }).then(() => {
|
||||
const limit = settings.get('explosionRadius');
|
||||
const explode = $e({
|
||||
tag: 'img',
|
||||
|
@ -408,13 +409,13 @@ window.Umi = { UI: {} };
|
|||
|
||||
for(const blMsg of backLog)
|
||||
Umi.Messages.Add(blMsg);
|
||||
}
|
||||
}).catch(() => {});
|
||||
}
|
||||
}, 'Clear Logs');
|
||||
|
||||
const pingIndicator = new MamiPingIndicator;
|
||||
const pingToggle = Umi.UI.Toggles.Add('ping', {
|
||||
click: () => alert(pingToggle.title),
|
||||
click: () => { ctx.msgbox.show({ body: `Your current ping is ${pingToggle.title}` }); },
|
||||
}, 'Ready~');
|
||||
pingToggle.appendChild(pingIndicator.getElement());
|
||||
|
||||
|
@ -451,7 +452,7 @@ window.Umi = { UI: {} };
|
|||
.then(() => uploadEntry.remove())
|
||||
.catch(ex => {
|
||||
console.error(ex);
|
||||
alert(ex);
|
||||
ctx.msgbox.show({ body: ['An error occurred while trying to delete an uploaded file:', ex] });
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -474,7 +475,7 @@ window.Umi = { UI: {} };
|
|||
} catch(ex) {
|
||||
if(!ex.aborted) {
|
||||
console.error(ex);
|
||||
alert(ex);
|
||||
ctx.msgbox.show({ body: ['An error occurred while trying to upload a file:', ex] });
|
||||
}
|
||||
|
||||
uploadEntry.remove();
|
||||
|
@ -515,13 +516,23 @@ window.Umi = { UI: {} };
|
|||
ev.preventDefault();
|
||||
|
||||
for(const file of ev.dataTransfer.files) {
|
||||
if(file.name.slice(-5) === '.mami'
|
||||
&& confirm('This file appears to be a settings export. Do you want to import it? This will overwrite your existing settings!')) {
|
||||
(new MamiSettingsBackup(settings)).importFile(file);
|
||||
return;
|
||||
}
|
||||
|
||||
if(doUpload !== undefined)
|
||||
if(file.name.slice(-5) === '.mami') {
|
||||
ctx.msgbox.show({
|
||||
body: [
|
||||
'This file appears to be a settings export.',
|
||||
'Do you want to import it? This will overwrite your existing settings!',
|
||||
],
|
||||
yes: true,
|
||||
no: true,
|
||||
})
|
||||
.then(() => {
|
||||
(new MamiSettingsBackup(settings)).importFile(file);
|
||||
})
|
||||
.catch(() => {
|
||||
if(doUpload !== undefined)
|
||||
doUpload(file);
|
||||
});
|
||||
} else if(doUpload !== undefined)
|
||||
doUpload(file);
|
||||
}
|
||||
});
|
||||
|
@ -539,7 +550,7 @@ window.Umi = { UI: {} };
|
|||
loadingOverlay.setMessage('Connecting...');
|
||||
|
||||
const setLoadingOverlay = async (icon, header, message, optional) => {
|
||||
const currentView = views.current();
|
||||
const currentView = ctx.views.current();
|
||||
|
||||
if('setIcon' in currentView) {
|
||||
currentView.setIcon(icon);
|
||||
|
@ -550,7 +561,7 @@ window.Umi = { UI: {} };
|
|||
|
||||
if(!optional) {
|
||||
const loading = new Umi.UI.LoadingOverlay(icon, header, message);
|
||||
await views.push(loading);
|
||||
await ctx.views.push(loading);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ Umi.UI.Hooks = (function() {
|
|||
if((ev.ctrlKey && ev.key !== 'v') || ev.altKey)
|
||||
return;
|
||||
|
||||
if(!ev.target.matches('input, textarea, select'))
|
||||
if(!ev.target.matches('input, textarea, select, button'))
|
||||
$i('umi-msg-text').focus();
|
||||
});
|
||||
|
||||
|
|
|
@ -231,7 +231,7 @@ Umi.UI.Settings = (function() {
|
|||
name: 'onlyConnectWhenVisible',
|
||||
title: 'Only connect when the tab is in the foreground',
|
||||
type: 'checkbox',
|
||||
confirm: 'Please only disable this setting if you are using a desktop or laptop computer, this should always remain on on a phone, tablet or other device of that sort. Ignoring this warning may carry consequences.',
|
||||
confirm: ['Please only disable this setting if you are using a desktop or laptop computer, this should always remain on on a phone, tablet or other device of that sort.', 'Are you sure you want to change this setting? Ignoring this warning may carry consequences.'],
|
||||
},
|
||||
{
|
||||
name: 'playJokeSounds',
|
||||
|
@ -346,10 +346,8 @@ Umi.UI.Settings = (function() {
|
|||
{
|
||||
title: 'Import settings',
|
||||
type: 'button',
|
||||
confirm: ['Your current settings will be replaced with the ones in the export.', 'Are you sure you want to continue?'],
|
||||
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.settings)).importUpload(document.body);
|
||||
},
|
||||
},
|
||||
|
@ -368,10 +366,8 @@ Umi.UI.Settings = (function() {
|
|||
{
|
||||
title: 'Reset settings',
|
||||
type: 'button',
|
||||
confirm: ['This will reset all your settings to their defaults values.', 'Are you sure you want to do this?'],
|
||||
invoke: () => {
|
||||
if(!confirm('This will reset all your settings to their defaults values. Are you sure you want to do this?'))
|
||||
return;
|
||||
|
||||
mami.settings.clear();
|
||||
},
|
||||
},
|
||||
|
@ -463,7 +459,16 @@ Umi.UI.Settings = (function() {
|
|||
</option>);
|
||||
} else if(display.type === 'button') {
|
||||
input.value = display.title;
|
||||
input.addEventListener('click', () => display.invoke(input));
|
||||
input.addEventListener('click', () => {
|
||||
if(display.confirm !== undefined)
|
||||
mami.msgbox.show({
|
||||
body: display.confirm,
|
||||
yes: { primary: false },
|
||||
no: { primary: true },
|
||||
}).then(() => { display.invoke(input); }).catch(() => {});
|
||||
else
|
||||
display.invoke(input);
|
||||
});
|
||||
}
|
||||
|
||||
if(setting !== undefined) {
|
||||
|
@ -473,12 +478,19 @@ Umi.UI.Settings = (function() {
|
|||
if(display.type === 'checkbox') {
|
||||
mami.settings.watch(setting.name, ev => input.checked = ev.detail.value);
|
||||
input.addEventListener('change', () => {
|
||||
if(display.confirm !== undefined && input.checked !== setting.fallback && !confirm(display.confirm)) {
|
||||
input.checked = setting.fallback;
|
||||
return;
|
||||
if(display.confirm !== undefined && input.checked !== setting.fallback) {
|
||||
mami.msgbox.show({
|
||||
body: display.confirm,
|
||||
yes: { primary: false },
|
||||
no: { primary: true },
|
||||
}).then(() => {
|
||||
mami.settings.toggle(setting.name);
|
||||
}).catch(() => {
|
||||
input.checked = setting.fallback;
|
||||
});
|
||||
} else {
|
||||
mami.settings.toggle(setting.name);
|
||||
}
|
||||
|
||||
mami.settings.toggle(setting.name);
|
||||
});
|
||||
} else {
|
||||
mami.settings.watch(setting.name, ev => input.value = ev.detail.value);
|
||||
|
|
|
@ -112,11 +112,15 @@ Umi.UI.Users = (function() {
|
|||
}));
|
||||
uOptions.appendChild(createAction('Kick Fucking Everyone', {
|
||||
'click': function() {
|
||||
if(confirm('You are about to detonate the fucking bomb. Are you sure?')) {
|
||||
const targets = Umi.Users.All();
|
||||
mami.msgbox.show({
|
||||
body: ['You are about to detonate the fucking bomb.', 'Are you sure?'],
|
||||
yes: { text: 'FUCK IT, WE BALL' },
|
||||
no: { text: 'nah' },
|
||||
}).then(() => {
|
||||
const targets = Umi.Users.All().reverse();
|
||||
for(const target of targets) // this shouldn't call it like this but will have to leave it for now
|
||||
Umi.Server.sendMessage('/kick ' + target.name);
|
||||
}
|
||||
}).catch(() => {});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue