489 lines
16 KiB
JavaScript
489 lines
16 KiB
JavaScript
const Umi = { UI: {} };
|
|
|
|
#include animate.js
|
|
#include common.js
|
|
#include context.js
|
|
#include emotes.js
|
|
#include messages.js
|
|
#include mszauth.js
|
|
#include server.js
|
|
#include settings.js
|
|
#include utility.js
|
|
#include ui/chat-layout.js
|
|
#include ui/domaintrans.jsx
|
|
#include ui/elems.js
|
|
#include ui/hooks.js
|
|
#include ui/input-menus.js
|
|
#include ui/loading-overlay.jsx
|
|
#include ui/markup.js
|
|
#include ui/menus.js
|
|
#include ui/view.js
|
|
#include ui/settings.js
|
|
#include ui/title.js
|
|
#include ui/toggles.js
|
|
#include ui/uploads.js
|
|
#include audio/context.js
|
|
#include eeprom/eeprom.js
|
|
|
|
(async () => {
|
|
const ctx = new MamiContext(document.body),
|
|
views = ctx.getViews();
|
|
|
|
Object.defineProperty(window, 'mami', {
|
|
value: ctx,
|
|
writable: false,
|
|
});
|
|
|
|
const sndLib = ctx.getSoundLibrary(),
|
|
sndPacks = ctx.getSoundPacks();
|
|
|
|
const lo = new Umi.UI.LoadingOverlay('spinner', 'Loading...');
|
|
await views.push(lo);
|
|
|
|
lo.setMessage('Loading environment...');
|
|
try {
|
|
window.futami = await FutamiCommon.load();
|
|
localStorage.setItem('mami:common', JSON.stringify(window.futami));
|
|
} catch(ex) {
|
|
try {
|
|
const cached = JSON.parse(localStorage.getItem('mami:common'));
|
|
if(cached === null)
|
|
throw 'Cached data is null.';
|
|
window.futami = new FutamiCommon(cached);
|
|
} catch(ex) {
|
|
console.error(ex);
|
|
lo.setIcon('cross');
|
|
lo.setHeader('Failed!');
|
|
lo.setMessage('Failed to load common settings!');
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
lo.setMessage('Fetching credentials...');
|
|
try {
|
|
const auth = await MamiMisuzuAuth.update();
|
|
if(!auth.ok)
|
|
throw 'Authentication failed.';
|
|
} catch(ex) {
|
|
console.error(ex);
|
|
location.assign(futami.get('login'));
|
|
return;
|
|
}
|
|
|
|
setInterval(() => {
|
|
MamiMisuzuAuth.update()
|
|
.then(auth => {
|
|
if(!auth.ok)
|
|
location.assign(futami.get('login'));
|
|
})
|
|
}, 600000);
|
|
|
|
|
|
lo.setMessage('Getting element references...');
|
|
|
|
// should be dynamic when possible
|
|
const layout = new Umi.UI.ChatLayout;
|
|
await views.unshift(layout);
|
|
|
|
Umi.UI.Elements.Chat = layout.getElement();
|
|
|
|
Umi.UI.Elements.Messages = $i('umi-messages');
|
|
Umi.UI.Elements.Menus = $i('umi-menus');
|
|
Umi.UI.Elements.Icons = $i('umi-menu-icons');
|
|
Umi.UI.Elements.Toggles = $i('umi-toggles');
|
|
Umi.UI.Elements.MessageContainer = $i('umi-msg-container');
|
|
Umi.UI.Elements.MessageInput = $i('umi-msg-text');
|
|
Umi.UI.Elements.MessageSend = $i('umi-msg-send');
|
|
Umi.UI.Elements.MessageMenus = $i('umi-msg-menu');
|
|
|
|
|
|
lo.setMessage('Loading sounds...');
|
|
try {
|
|
const sounds = await futami.getJson('sounds2');
|
|
if(Array.isArray(sounds.library))
|
|
sndLib.loadSounds(sounds.library, true);
|
|
if(Array.isArray(sounds.packs))
|
|
sndPacks.loadPacks(sounds.packs, true);
|
|
} catch(ex) {
|
|
console.error(ex);
|
|
}
|
|
|
|
|
|
lo.setMessage('Loading emoticons...');
|
|
try {
|
|
const emotes = await futami.getJson('emotes');
|
|
MamiEmotes.loadLegacy(emotes);
|
|
} catch(ex) {
|
|
console.error(ex);
|
|
}
|
|
|
|
|
|
lo.setMessage('Loading settings...');
|
|
|
|
Umi.Settings = new Umi.Settings(UmiSettings.settings);
|
|
|
|
if(!await MamiDetectAutoPlay()) {
|
|
Umi.Settings.set('soundEnable', false);
|
|
Umi.Settings.virtualise('soundEnable');
|
|
}
|
|
|
|
const meta = UmiSettings.settings;
|
|
for(const setting of UmiSettings.settings)
|
|
if(setting.watcher)
|
|
Umi.Settings.watch(setting.id, setting.watcher);
|
|
|
|
|
|
if(!Umi.Settings.get('tmpSkipDomainPopUpThing'))
|
|
await (() => {
|
|
return new Promise((resolve) => {
|
|
views.push(new MamiDomainTransition(() => {
|
|
for(const setting of UmiSettings.settings)
|
|
if(setting.id === 'settingsImport') {
|
|
setting.click();
|
|
break;
|
|
}
|
|
}, () => {
|
|
Umi.Settings.set('tmpSkipDomainPopUpThing', true);
|
|
views.pop();
|
|
resolve();
|
|
}));
|
|
});
|
|
})();
|
|
|
|
|
|
const onHashChange = () => {
|
|
if(location.hash === '#reset') {
|
|
for(const setting of UmiSettings.settings)
|
|
if(setting.emergencyReset)
|
|
Umi.Settings.remove(setting.id);
|
|
|
|
location.assign('/');
|
|
}
|
|
};
|
|
|
|
window.addEventListener('hashchange', onHashChange);
|
|
onHashChange();
|
|
|
|
window.addEventListener('keydown', ev => {
|
|
if(ev.altKey && ev.shiftKey && (ev.key === 'R' || ev.key === 'r')) {
|
|
Umi.Server.close();
|
|
location.hash = 'reset';
|
|
}
|
|
});
|
|
|
|
|
|
lo.setMessage('Preparing UI...');
|
|
|
|
Umi.UI.Title.Set(futami.get('title'));
|
|
Umi.UI.View.AccentReload();
|
|
Umi.UI.Hooks.AddMessageHooks();
|
|
Umi.UI.Hooks.AddUserHooks();
|
|
Umi.UI.Hooks.AddChannelHooks();
|
|
Umi.UI.Hooks.AddTextHooks();
|
|
|
|
const mcPortalSnd = 'minecraft:nether:enter';
|
|
if(Umi.Settings.get('minecraft') !== 'no' && ctx.hasSound() && sndLib.hasSound(mcPortalSnd))
|
|
ctx.getSound().load(mcPortalSnd, sndLib.getSound(mcPortalSnd).getSources(), function(success, buffer) {
|
|
if(success)
|
|
buffer.createSource().play();
|
|
});
|
|
|
|
|
|
lo.setMessage('Loading EEPROM...');
|
|
try {
|
|
await MamiEEPROM.init();
|
|
ctx.createEEPROM(
|
|
futami.get('eeprom'),
|
|
function() { return 'Misuzu ' + MamiMisuzuAuth.getAuthToken(); }
|
|
);
|
|
} catch(ex) {
|
|
console.error(ex);
|
|
}
|
|
|
|
|
|
lo.setMessage('Building menus...');
|
|
|
|
Umi.UI.Menus.Add('users', 'Users');
|
|
Umi.UI.Menus.Add('channels', 'Channels', !Umi.Settings.get('showChannelList'));
|
|
Umi.UI.Menus.Add('settings', 'Settings');
|
|
|
|
let sidebarAnimation = null;
|
|
|
|
Umi.UI.Settings.Init();
|
|
Umi.UI.Toggles.Add('menu-toggle', {
|
|
'click': function() {
|
|
const sidebar = $c('sidebar')[0],
|
|
toggle = Umi.UI.Toggles.Get('menu-toggle'),
|
|
toggleOpened = 'sidebar__selector-mode--menu-toggle-opened',
|
|
toggleClosed = 'sidebar__selector-mode--menu-toggle-closed',
|
|
isClosed = toggle.classList.contains(toggleClosed);
|
|
|
|
if(sidebarAnimation !== null) {
|
|
sidebarAnimation.cancel();
|
|
sidebarAnimation = null;
|
|
}
|
|
|
|
if(isClosed) {
|
|
toggle.classList.add(toggleOpened);
|
|
toggle.classList.remove(toggleClosed);
|
|
} else {
|
|
toggle.classList.add(toggleClosed);
|
|
toggle.classList.remove(toggleOpened);
|
|
}
|
|
|
|
let update;
|
|
if(isClosed)
|
|
update = function(t) {
|
|
sidebar.style.width = (40 + (220 * t)).toString() + 'px';
|
|
};
|
|
else
|
|
update = function(t) {
|
|
sidebar.style.width = (260 - (220 * t)).toString() + 'px';
|
|
};
|
|
|
|
sidebarAnimation = MamiAnimate({
|
|
duration: 500,
|
|
easing: 'easeOutExpo',
|
|
update: update,
|
|
});
|
|
}
|
|
}, 'Toggle Sidebar');
|
|
|
|
Umi.UI.Toggles.Get('menu-toggle').classList.add('sidebar__selector-mode--menu-toggle-opened');
|
|
|
|
Umi.UI.Toggles.Add('scroll', {
|
|
'click': function() {
|
|
Umi.Settings.toggle('autoScroll');
|
|
}
|
|
}, 'Autoscroll');
|
|
Umi.Settings.watch('autoScroll', function(value) {
|
|
Umi.UI.Toggles.Get('scroll').classList[value ? 'remove' : 'add']('sidebar__selector-mode--scroll-off');
|
|
});
|
|
|
|
if(window.innerWidth < 768)
|
|
Umi.UI.Toggles.Get('menu-toggle').click();
|
|
|
|
Umi.UI.Toggles.Add('audio', {
|
|
'click': function() {
|
|
Umi.Settings.toggle('soundEnable');
|
|
}
|
|
}, 'Sounds');
|
|
Umi.Settings.watch('soundEnable', function(value) {
|
|
Umi.UI.Toggles.Get('audio').classList[value ? 'remove' : 'add']('sidebar__selector-mode--audio-off');
|
|
});
|
|
|
|
Umi.UI.Toggles.Add('unembed', {
|
|
'click': function() {
|
|
const buttons = $qa('[data-embed="1"]');
|
|
for(const button of buttons)
|
|
button.click();
|
|
}
|
|
}, 'Unembed any embedded media');
|
|
|
|
Umi.UI.Toggles.Add('clear', {
|
|
'click': function() {
|
|
if(confirm('ARE YOU SURE ABOUT THAT???')) {
|
|
const limit = Umi.Settings.get('explosionRadius');
|
|
const explode = $e({
|
|
tag: 'img',
|
|
attrs: {
|
|
src: '//static.flash.moe/images/explode.gif',
|
|
alt: '',
|
|
style: {
|
|
position: 'absolute',
|
|
zIndex: 9001,
|
|
bottom: 0,
|
|
right: 0,
|
|
pointerEvents: 'none',
|
|
},
|
|
onLoad: function() {
|
|
setTimeout(function(){
|
|
$r(explode);
|
|
}, 1700);
|
|
|
|
ctx.playLibrarySound('misc:explode');
|
|
},
|
|
},
|
|
});
|
|
|
|
document.body.appendChild(explode);
|
|
|
|
let backLog = Umi.Messages.All();
|
|
backLog = backLog.slice(Math.max(backLog.length - limit, 0));
|
|
|
|
Umi.Messages.Clear();
|
|
|
|
for(const blMsg of backLog)
|
|
Umi.Messages.Add(blMsg);
|
|
}
|
|
}
|
|
}, 'Clear Logs');
|
|
|
|
|
|
if(ctx.hasEEPROM()) {
|
|
Umi.UI.Menus.Add('uploads', 'Upload History', !FUTAMI_DEBUG);
|
|
|
|
const doUpload = function(file) {
|
|
const uploadEntry = Umi.UI.Uploads.create(file.name),
|
|
uploadTask = ctx.getEEPROM().createUpload(file);
|
|
|
|
uploadTask.onProgress = function(progressInfo) {
|
|
uploadEntry.setProgress(progressInfo.total, progressInfo.loaded);
|
|
};
|
|
|
|
uploadTask.onFailure = function(errorInfo) {
|
|
if(!errorInfo.userAborted) {
|
|
let errorText = 'Was unable to upload file.';
|
|
|
|
switch(errorInfo.error) {
|
|
case EEPROM.ERR_INVALID:
|
|
errorText = 'Upload request was invalid.';
|
|
break;
|
|
case EEPROM.ERR_AUTH:
|
|
errorText = 'Upload authentication failed, refresh and try again.';
|
|
break;
|
|
case EEPROM.ERR_ACCESS:
|
|
errorText = 'You\'re not allowed to upload files.';
|
|
break;
|
|
case EEPROM.ERR_GONE:
|
|
errorText = 'Upload client has a configuration error or the server is gone.';
|
|
break;
|
|
case EEPROM.ERR_DMCA:
|
|
errorText = 'This file has been uploaded before and was removed for copyright reasons, you cannot upload this file.';
|
|
break;
|
|
case EEPROM.ERR_SERVER:
|
|
errorText = 'Upload server returned a critical error, try again later.';
|
|
break;
|
|
case EEPROM.ERR_SIZE:
|
|
if(errorInfo.maxSize < 1)
|
|
errorText = 'Selected file is too large.';
|
|
else {
|
|
const _t = ['bytes', 'KB', 'MB', 'GB', 'TB'],
|
|
_i = parseInt(Math.floor(Math.log(errorInfo.maxSize) / Math.log(1024))),
|
|
_s = Math.round(errorInfo.maxSize / Math.pow(1024, _i), 2);
|
|
|
|
errorText = 'Upload may not be larger than %1 %2.'.replace('%1', _s).replace('%2', _t[_i]);
|
|
}
|
|
break;
|
|
}
|
|
|
|
alert(errorText);
|
|
}
|
|
|
|
uploadEntry.remove();
|
|
};
|
|
|
|
uploadTask.onComplete = function(fileInfo) {
|
|
uploadEntry.hideOptions();
|
|
uploadEntry.clearOptions();
|
|
uploadEntry.removeProgress();
|
|
|
|
uploadEntry.addOption('Open', fileInfo.url);
|
|
uploadEntry.addOption('Insert', function() {
|
|
Umi.UI.Markup.InsertRaw(insertText, '');
|
|
});
|
|
uploadEntry.addOption('Delete', function() {
|
|
ctx.getEEPROM().deleteUpload(fileInfo).start();
|
|
uploadEntry.remove();
|
|
});
|
|
|
|
let insertText = location.protocol + fileInfo.url;
|
|
|
|
if(fileInfo.isImage()) {
|
|
insertText = '[img]' + fileInfo.url + '[/img]';
|
|
uploadEntry.setThumbnail(fileInfo.thumb);
|
|
} else if(fileInfo.isAudio() || fileInfo.type === 'application/x-font-gdos') {
|
|
insertText = '[audio]' + fileInfo.url + '[/audio]';
|
|
uploadEntry.setThumbnail(fileInfo.thumb);
|
|
} else if(fileInfo.isVideo()) {
|
|
insertText = '[video]' + fileInfo.url + '[/video]';
|
|
uploadEntry.setThumbnail(fileInfo.thumb);
|
|
}
|
|
|
|
|
|
if(Umi.Settings.get('eepromAutoInsert'))
|
|
Umi.UI.Markup.InsertRaw(insertText, '');
|
|
};
|
|
|
|
uploadEntry.addOption('Cancel', function() {
|
|
uploadTask.abort();
|
|
});
|
|
|
|
uploadTask.start();
|
|
};
|
|
|
|
const uploadForm = $e({
|
|
tag: 'input',
|
|
attrs: {
|
|
type: 'file',
|
|
multiple: true,
|
|
style: {
|
|
display: 'none',
|
|
},
|
|
onchange: function(ev) {
|
|
for(let i = 0; i < ev.target.files.length; ++i)
|
|
doUpload(ev.target.files[i]);
|
|
},
|
|
},
|
|
});
|
|
document.body.appendChild(uploadForm);
|
|
|
|
Umi.UI.InputMenus.AddButton('upload', 'Upload', function() {
|
|
uploadForm.click();
|
|
});
|
|
|
|
Umi.UI.Elements.MessageInput.onpaste = function(ev) {
|
|
if(ev.clipboardData && ev.clipboardData.files.length > 0)
|
|
for(const file of ev.clipboardData.files)
|
|
doUpload(file);
|
|
};
|
|
|
|
document.body.ondragenter = function(ev) {
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
};
|
|
document.body.ondragover = function(ev) {
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
};
|
|
document.body.ondragleave = function(ev) {
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
};
|
|
document.body.ondrop = function(ev) {
|
|
ev.preventDefault();
|
|
ev.stopPropagation();
|
|
if(ev.dataTransfer && ev.dataTransfer.files.length > 0)
|
|
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?')) {
|
|
Umi.Settings.importFile(file);
|
|
return;
|
|
}
|
|
|
|
doUpload(file);
|
|
}
|
|
};
|
|
}
|
|
|
|
Umi.UI.InputMenus.Add('markup', 'BB Code');
|
|
Umi.UI.InputMenus.Add('emotes', 'Emoticons');
|
|
|
|
window.addEventListener('beforeunload', function(ev) {
|
|
if(Umi.Settings.get('closeTabConfirm')) {
|
|
ev.preventDefault();
|
|
return ev.returnValue = 'Are you sure you want to close the tab?';
|
|
}
|
|
});
|
|
|
|
|
|
lo.setMessage('Connecting...');
|
|
Umi.Server.open(views);
|
|
|
|
if(window.dispatchEvent)
|
|
window.dispatchEvent(new Event('umi:connect'));
|
|
})();
|
|
|
|
#include compat.js
|