Compare commits

...

7 commits

7 changed files with 131 additions and 43 deletions

View file

@ -13,6 +13,7 @@
justify-content: center;
align-items: center;
grid-template-columns: 340px;
z-index: 88888888;
}
.msgbox-dialog {

View file

@ -37,8 +37,15 @@
.sidebar__selector-top {
flex-grow: 1;
flex-shrink: 0;
overflow: hidden;
}
.sidebar__selector-bottom {
flex-shrink: 1;
flex-grow: 0;
overflow: hidden auto;
scrollbar-width: thin;
}
.sidebar__selector-mode {
height: 40px;

View file

@ -49,6 +49,9 @@ const MamiAnimate = info => {
easing = MamiEasings.linear;
}
if(typeof window.mami?.settings?.get === 'function')
duration *= mami.settings.get('dbgAnimDurationMulti');
let tStart, tLast,
cancel = false,
tRawCompletion = 0,

View file

@ -4,16 +4,68 @@
const MamiMessageBoxContainer = function() {
const container = <div class="msgbox-container"/>;
let raised = false;
let currAnim;
return {
getElement: () => container,
raise: async parent => {
if(raised) return;
raised = true;
container.style.pointerEvents = null;
if(!parent.contains(container))
parent.appendChild(container);
currAnim?.cancel();
currAnim = MamiAnimate({
async: true,
delayed: true,
duration: 300,
easing: 'outExpo',
start: () => { container.style.opacity = '0'; },
update: t => { container.style.opacity = t; },
end: () => { container.style.opacity = null; },
});
try {
await currAnim.start();
} catch(ex) {}
},
dismiss: async parent => {
if(!raised) return;
raised = false;
container.style.pointerEvents = 'none';
currAnim?.cancel();
currAnim = MamiAnimate({
async: true,
delayed: true,
duration: 300,
easing: 'outExpo',
update: t => { container.style.opacity = 1 - t; },
end: t => { parent.removeChild(container); },
});
try {
await currAnim.start();
} catch(ex) {}
},
show: async dialog => {
if(typeof dialog !== 'object' || dialog === null)
throw 'dialog must be a non-null object';
const backgroundClick = ev => {
ev.stopPropagation();
if(ev.target === container)
dialog.clickButtonIndex(0);
};
try {
if(dialog.buttonCount === 1)
container.addEventListener('click', backgroundClick);
return await dialog.show(container);
} finally {
container.removeEventListener('click', backgroundClick);
dialog.dismiss();
}
},
@ -28,6 +80,7 @@ const MamiMessageBoxDialog = function(info) {
{ name: 'cancel', text: 'Cancel', reject: true },
];
const dialog = <form class="msgbox-dialog"/>;
let showResolve, showReject;
const doResolve = (...args) => {
@ -35,6 +88,7 @@ const MamiMessageBoxDialog = function(info) {
return;
showReject = undefined;
dialog.style.pointerEvents = 'none';
showResolve(...args);
};
const doReject = (...args) => {
@ -42,11 +96,10 @@ const MamiMessageBoxDialog = function(info) {
return;
showResolve = undefined;
dialog.style.pointerEvents = 'none';
showReject(...args);
};
const dialog = <form class="msgbox-dialog"/>;
const body = <div class="msgbox-dialog-body"/>;
dialog.appendChild(body);
@ -116,7 +169,13 @@ const MamiMessageBoxDialog = function(info) {
buttons.classList.add('msgbox-dialog-buttons-many');
return {
getElement: () => dialog,
get buttonCount() {
return buttons.childElementCount;
},
clickButtonIndex: num => {
buttons.children[num].click();
},
show: container => {
return new Promise((resolve, reject) => {
showResolve = resolve;
@ -160,6 +219,8 @@ const MamiMessageBoxDialog = function(info) {
});
},
dismiss: async () => {
dialog.style.pointerEvents = 'none';
await MamiAnimate({
async: true,
duration: 600,
@ -178,10 +239,10 @@ const MamiMessageBoxDialog = function(info) {
const MamiMessageBoxControl = function(options) {
options = MamiArguments.verify(options, [
MamiArguments.type('views', 'object', undefined, true),
MamiArguments.check('parent', undefined, value => value instanceof Element, true),
]);
const views = options.views;
const parent = options.parent;
const container = new MamiMessageBoxContainer;
const queue = [];
let currentDialog;
@ -214,14 +275,7 @@ const MamiMessageBoxControl = function(options) {
};
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; },
}));
container.raise(parent);
if(!processingQueue)
await processQueue();
@ -229,16 +283,8 @@ const MamiMessageBoxControl = function(options) {
const dismiss = async () => {
processingQueue = false;
container.dismiss(parent);
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 {

View file

@ -42,7 +42,7 @@ window.Umi = { UI: {} };
Object.defineProperty(window, 'mami', { enumerable: true, value: ctx });
ctx.views = new MamiViewsControl({ body: document.body });
ctx.msgbox = new MamiMessageBoxControl({ views: ctx.views });
ctx.msgbox = new MamiMessageBoxControl({ parent: document.body });
const loadingOverlay = new Umi.UI.LoadingOverlay('spinner', 'Loading...');
await ctx.views.push(loadingOverlay);
@ -99,7 +99,7 @@ window.Umi = { UI: {} };
settings.define('autoEmbedV1').default(false).create();
settings.define('soundEnable').default(true).critical().create();
settings.define('soundPack').default('').create();
settings.define('soundVolume').default(80).create();
settings.define('soundVolume').default(80).min(0).max(100).create();
settings.define('soundEnableJoin').default(true).create();
settings.define('soundEnableLeave').default(true).create();
settings.define('soundEnableError').default(true).create();
@ -121,11 +121,12 @@ window.Umi = { UI: {} };
settings.define('motivationalVideos').default(false).create();
settings.define('osuKeys').default(false).create();
settings.define('osuKeysV2').type(['no', 'yes', 'rng']).default('no').create();
settings.define('explosionRadius').default(20).create();
settings.define('explosionRadius').default(20).min(0).create();
settings.define('dumpPackets').default(FUTAMI_DEBUG).create();
settings.define('dumpEvents').default(FUTAMI_DEBUG).create();
settings.define('marqueeAllNames').default(false).create();
settings.define('tmpDisableOldThemeSys').default(false).critical().create();
settings.define('dbgAnimDurationMulti').default(1).min(0).max(10).create();
const noNotifSupport = !('Notification' in window);
settings.define('enableNotifications').default(false).immutable(noNotifSupport).critical().create();

View file

@ -71,6 +71,11 @@ const MamiSettings = function(storageOrPrefix, eventTarget) {
if(setting.type === 'number') {
value = parseFloat(value);
resolved = true;
if(setting.min !== undefined && value < setting.min)
value = setting.min;
else if(setting.max !== undefined && value > setting.max)
value = setting.max;
} else if(setting.type === 'boolean') {
value = !!value;
resolved = true;
@ -122,11 +127,16 @@ const MamiSettings = function(storageOrPrefix, eventTarget) {
checkDefined();
let created = false;
let type = undefined;
let fallback = null;
let immutable = false;
let critical = false;
let virtual = false;
const setting = {
name: name,
type: undefined,
fallback: null,
immutable: false,
critical: false,
min: undefined,
max: undefined,
};
const checkCreated = () => {
if(created)
@ -140,26 +150,42 @@ const MamiSettings = function(storageOrPrefix, eventTarget) {
checkCreated();
type = value;
setting.type = value;
return pub;
},
default: value => {
checkCreated();
fallback = value === undefined ? null : value;
setting.fallback = value === undefined ? null : value;
if(type === undefined)
type = typeof fallback;
if(setting.type === undefined)
setting.type = typeof setting.fallback;
return pub;
},
immutable: value => {
checkCreated();
immutable = value === undefined || value === true;
setting.immutable = value === undefined || value === true;
return pub;
},
critical: value => {
checkCreated();
critical = value === undefined || value === true;
setting.critical = value === undefined || value === true;
return pub;
},
min: value => {
checkCreated();
if(typeof value !== 'number')
throw 'value must be a number';
setting.min = value;
return pub;
},
max: value => {
checkCreated();
if(typeof value !== 'number')
throw 'value must be a number';
setting.max = value;
return pub;
},
virtual: value => {
@ -171,13 +197,7 @@ const MamiSettings = function(storageOrPrefix, eventTarget) {
checkCreated();
checkDefined();
settings.set(name, Object.freeze({
name: name,
type: type,
fallback: fallback,
immutable: immutable,
critical: critical,
}));
settings.set(name, Object.freeze(setting));
if(virtual)
storage.virtualise(name);

View file

@ -399,6 +399,11 @@ Umi.UI.Settings = (function() {
title: 'Disable Old Theme System',
type: 'checkbox',
},
{
name: 'dbgAnimDurationMulti',
title: 'Animation multiplier',
type: 'range',
},
{
title: 'Test kick/ban notice',
type: 'button',
@ -475,6 +480,11 @@ Umi.UI.Settings = (function() {
if(!input.disabled && setting.immutable)
input.disabled = true;
if(setting.min !== undefined)
input.min = setting.min;
if(setting.max !== undefined)
input.max = setting.max;
if(display.type === 'checkbox') {
mami.settings.watch(setting.name, ev => input.checked = ev.detail.value);
input.addEventListener('change', () => {