Attempts at making message rendering and notifications more consistent and moved a lot of UI stuff out of the protocol handler.
This commit is contained in:
parent
c0246909c0
commit
cdabf80e1c
12 changed files with 491 additions and 765 deletions
|
@ -25,6 +25,7 @@ const MamiCompat = (current, path, handler) => {
|
||||||
// Backwards compat for scripts
|
// Backwards compat for scripts
|
||||||
// Keep in sync with <https://fii.moe/fp/13176> for as long as possible
|
// Keep in sync with <https://fii.moe/fp/13176> for as long as possible
|
||||||
MamiCompat(Umi, 'Server.SendMessage', text => Umi.Server.sendMessage(text));
|
MamiCompat(Umi, 'Server.SendMessage', text => Umi.Server.sendMessage(text));
|
||||||
|
MamiCompat(Umi, 'Protocol.SockChat.Protocol.Instance.SendMessage', text => Umi.Server.sendMessage(text));
|
||||||
MamiCompat(Umi, 'Protocol.SockLegacy.Protocol.Instance.SendMessage', text => Umi.Server.sendMessage(text));
|
MamiCompat(Umi, 'Protocol.SockLegacy.Protocol.Instance.SendMessage', text => Umi.Server.sendMessage(text));
|
||||||
MamiCompat(Umi, 'Parser.SockChatBBcode.EmbedStub', () => {}); // intentionally a no-op
|
MamiCompat(Umi, 'Parser.SockChatBBcode.EmbedStub', () => {}); // intentionally a no-op
|
||||||
MamiCompat(Umi, 'UI.View.SetText', text => console.log(`Umi.UI.View.SetText(text: ${text})`));
|
MamiCompat(Umi, 'UI.View.SetText', text => console.log(`Umi.UI.View.SetText(text: ${text})`));
|
||||||
|
|
|
@ -98,7 +98,6 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
||||||
settings.define('soundEnablePrivate', 'boolean', true);
|
settings.define('soundEnablePrivate', 'boolean', true);
|
||||||
settings.define('soundEnableForceLeave', 'boolean', true);
|
settings.define('soundEnableForceLeave', 'boolean', true);
|
||||||
settings.define('minecraft', ['no', 'yes', 'old'], 'no');
|
settings.define('minecraft', ['no', 'yes', 'old'], 'no');
|
||||||
settings.define('playSoundOnConnect', 'boolean', false);
|
|
||||||
settings.define('windowsLiveMessenger', 'boolean', false);
|
settings.define('windowsLiveMessenger', 'boolean', false);
|
||||||
settings.define('seinfeld', 'boolean', false);
|
settings.define('seinfeld', 'boolean', false);
|
||||||
settings.define('flashTitle', 'boolean', true);
|
settings.define('flashTitle', 'boolean', true);
|
||||||
|
@ -149,7 +148,7 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
||||||
settings.touch('soundVolume');
|
settings.touch('soundVolume');
|
||||||
settings.touch('soundPack');
|
settings.touch('soundPack');
|
||||||
|
|
||||||
soundCtx.packPlayer.playEvent('server');
|
soundCtx.library.play(soundCtx.pack.getEventSound('server'));
|
||||||
}
|
}
|
||||||
|
|
||||||
soundCtx.muted = !v;
|
soundCtx.muted = !v;
|
||||||
|
@ -162,9 +161,8 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const player = soundCtx.packPlayer;
|
soundCtx.pack = packs.get(v);
|
||||||
player.loadPack(packs.get(v));
|
if(!i) soundCtx.library.play(soundCtx.pack.getEventSound('server'));
|
||||||
if(!i) player.playEvent('server');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
settings.watch('soundVolume', v => {
|
settings.watch('soundVolume', v => {
|
||||||
|
@ -252,12 +250,18 @@ window.Umi = { UI: {}, Protocol: { SockChat: { Protocol: {} } } };
|
||||||
settings.watch('tmpDisableOldThemeSys', (v, n, i) => { if(!i) Umi.UI.View.AccentReload(); });
|
settings.watch('tmpDisableOldThemeSys', (v, n, i) => { if(!i) Umi.UI.View.AccentReload(); });
|
||||||
|
|
||||||
settings.watch('minecraft', (v, n, i) => {
|
settings.watch('minecraft', (v, n, i) => {
|
||||||
if(v !== 'no') {
|
if(i && v === 'no')
|
||||||
|
return;
|
||||||
|
|
||||||
|
soundCtx.library.play((() => {
|
||||||
if(i)
|
if(i)
|
||||||
soundCtx.library.play('minecraft:nether:enter');
|
return 'minecraft:nether:enter';
|
||||||
else
|
if(v === 'yes')
|
||||||
Umi.Sound.Play('join');
|
return 'minecraft:door:open';
|
||||||
}
|
if(v === 'old')
|
||||||
|
return 'minecraft:door:open-old';
|
||||||
|
return mami.sound.pack.getEventSound('join');
|
||||||
|
})());
|
||||||
});
|
});
|
||||||
|
|
||||||
settings.watch('enableNotifications', v => {
|
settings.watch('enableNotifications', v => {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Umi.Message = function(msgId, time, user, text, channel, highlight, botInfo, isAction) {
|
Umi.Message = function(msgId, time, user, text, channel, highlight, botInfo, isAction, isLog) {
|
||||||
msgId = (msgId || '').toString();
|
msgId = (msgId || '').toString();
|
||||||
time = time === null ? new Date() : new Date(parseInt(time || 0) * 1000);
|
time = time === null ? new Date() : new Date(parseInt(time || 0) * 1000);
|
||||||
user = user || {};
|
user = user || {};
|
||||||
|
@ -6,18 +6,23 @@ Umi.Message = function(msgId, time, user, text, channel, highlight, botInfo, isA
|
||||||
channel = (channel || '').toString();
|
channel = (channel || '').toString();
|
||||||
highlight = !!highlight;
|
highlight = !!highlight;
|
||||||
isAction = !!isAction;
|
isAction = !!isAction;
|
||||||
|
isLog = !!isLog;
|
||||||
|
hasSeen = isLog;
|
||||||
|
|
||||||
const msgIdInt = parseInt(msgId);
|
const msgIdInt = parseInt(msgId);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getId: function() { return msgId; },
|
getId: () => msgId,
|
||||||
getIdInt: function() { return msgIdInt; },
|
getIdInt: () => msgIdInt,
|
||||||
getTime: function() { return time; },
|
getTime: () => time,
|
||||||
getUser: function() { return user; },
|
getUser: () => user,
|
||||||
getText: function() { return text; },
|
getText: () => text,
|
||||||
getChannel: function() { return channel; },
|
getChannel: () => channel,
|
||||||
shouldHighlight: function() { return highlight; },
|
shouldHighlight: () => highlight,
|
||||||
getBotInfo: function() { return botInfo; },
|
getBotInfo: () => botInfo,
|
||||||
isAction: function() { return isAction; },
|
isAction: () => isAction,
|
||||||
|
isLog: () => isLog,
|
||||||
|
hasSeen: () => hasSeen,
|
||||||
|
markSeen: () => hasSeen = true,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,24 +1,16 @@
|
||||||
#include channels.js
|
#include channels.js
|
||||||
#include server.js
|
#include server.js
|
||||||
|
#include ui/messages.jsx
|
||||||
|
|
||||||
Umi.Messages = (function() {
|
Umi.Messages = (function() {
|
||||||
const msgs = new Map;
|
const msgs = new Map;
|
||||||
|
|
||||||
const onAdd = [],
|
|
||||||
onRemove = [],
|
|
||||||
onClear = [];
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
OnAdd: onAdd,
|
|
||||||
OnRemove: onRemove,
|
|
||||||
OnClear: onClear,
|
|
||||||
Add: function(msg) {
|
Add: function(msg) {
|
||||||
const msgId = msg.getId();
|
const msgId = msg.getId();
|
||||||
if(!msgs.has(msgId)) {
|
if(!msgs.has(msgId)) {
|
||||||
msgs.set(msgId, msg);
|
msgs.set(msgId, msg);
|
||||||
|
Umi.UI.Messages.Add(msg);
|
||||||
for(const i in onAdd)
|
|
||||||
onAdd[i](msg);
|
|
||||||
|
|
||||||
if(window.CustomEvent)
|
if(window.CustomEvent)
|
||||||
window.dispatchEvent(new CustomEvent('umi:message_add', {
|
window.dispatchEvent(new CustomEvent('umi:message_add', {
|
||||||
|
@ -30,16 +22,12 @@ Umi.Messages = (function() {
|
||||||
const msgId = msg.getId();
|
const msgId = msg.getId();
|
||||||
if(msgs.has(msgId)) {
|
if(msgs.has(msgId)) {
|
||||||
msgs.delete(msgId);
|
msgs.delete(msgId);
|
||||||
|
Umi.UI.Messages.Remove(msg);
|
||||||
for(const i in onRemove)
|
|
||||||
onRemove[i](msg);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Clear: function() {
|
Clear: function() {
|
||||||
msgs.clear();
|
msgs.clear();
|
||||||
|
Umi.UI.Messages.RemoveAll();
|
||||||
for(const i in onClear)
|
|
||||||
onClear[i]();
|
|
||||||
},
|
},
|
||||||
All: function(channel, excludeNull) {
|
All: function(channel, excludeNull) {
|
||||||
if(!channel)
|
if(!channel)
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include users.js
|
#include users.js
|
||||||
#include parsing.js
|
#include parsing.js
|
||||||
#include servers.js
|
#include servers.js
|
||||||
#include txtrigs.js
|
|
||||||
#include websock.js
|
#include websock.js
|
||||||
#include ui/emotes.js
|
#include ui/emotes.js
|
||||||
#include ui/markup.js
|
#include ui/markup.js
|
||||||
|
@ -16,11 +15,9 @@
|
||||||
#include ui/messages.jsx
|
#include ui/messages.jsx
|
||||||
#include ui/view.js
|
#include ui/view.js
|
||||||
#include ui/loading-overlay.jsx
|
#include ui/loading-overlay.jsx
|
||||||
#include sound/umisound.js
|
|
||||||
|
|
||||||
Umi.Protocol.SockChat.Protocol = function(views, settings) {
|
Umi.Protocol.SockChat.Protocol = function(views, settings) {
|
||||||
const pub = {};
|
const pub = {};
|
||||||
Umi.Protocol.SockChat.Protocol.Instance = pub;
|
|
||||||
|
|
||||||
const chatBot = new Umi.User('-1', 'Server');
|
const chatBot = new Umi.User('-1', 'Server');
|
||||||
|
|
||||||
|
@ -165,7 +162,6 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
|
||||||
|
|
||||||
getLoadingOverlay('unlink', 'Disconnected!', msg);
|
getLoadingOverlay('unlink', 'Disconnected!', msg);
|
||||||
|
|
||||||
//Umi.Messages.Clear();
|
|
||||||
Umi.Users.Clear();
|
Umi.Users.Clear();
|
||||||
|
|
||||||
connectAttempts = 0;
|
connectAttempts = 0;
|
||||||
|
@ -175,225 +171,6 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
|
||||||
}, 5000);
|
}, 5000);
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseBotMessage = function(parts) {
|
|
||||||
let text = '';
|
|
||||||
|
|
||||||
switch(parts[1]) {
|
|
||||||
case 'silence':
|
|
||||||
text = 'You have been silenced!';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'unsil':
|
|
||||||
text = 'You are no longer silenced!';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'silok':
|
|
||||||
text = '{0} is now silenced.'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'usilok':
|
|
||||||
text = '{0} is no longer silenced.'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'flood':
|
|
||||||
text = '{0} got kicked for flood protection.'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'flwarn':
|
|
||||||
text = 'You are about to hit the flood limit! If you continue you will be kicked.';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'unban':
|
|
||||||
text = '{0} is no longer banned.'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'banlist':
|
|
||||||
const blentries = parts[2].split(', ');
|
|
||||||
for(const i in blentries)
|
|
||||||
blentries[i] = blentries[i].slice(92, -4);
|
|
||||||
|
|
||||||
text = 'Banned: {0}'.replace('{0}', blentries.join(', '));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'who':
|
|
||||||
const wentries = parts[2].split(', ');
|
|
||||||
for(const i in wentries) {
|
|
||||||
const isSelf = wentries[i].includes(' style="font-weight: bold;"');
|
|
||||||
wentries[i] = wentries[i].slice(isSelf ? 102 : 75, -4);
|
|
||||||
if(isSelf) wentries[i] += ' (You)';
|
|
||||||
}
|
|
||||||
|
|
||||||
text = 'Online: {0}'.replace('{0}', wentries.join(', '));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'whochan':
|
|
||||||
const wcentries = (parts[3] || '').split(', ');
|
|
||||||
for(const i in wcentries) {
|
|
||||||
const isSelf = wcentries[i].includes(' style="font-weight: bold;"');
|
|
||||||
wcentries[i] = wcentries[i].slice(isSelf ? 102 : 75, -4);
|
|
||||||
if(isSelf) wcentries[i] += ' (You)';
|
|
||||||
}
|
|
||||||
|
|
||||||
text = 'Online in {0}: {1}'.replace('{0}', parts[2]).replace('{1}', wcentries.join(', '));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'silerr':
|
|
||||||
text = 'This user has already been silenced!';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'usilerr':
|
|
||||||
text = "This user isn't silenced!";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'silperr':
|
|
||||||
text = "You aren't allowed to silence this user!";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'usilperr':
|
|
||||||
text = "You aren't allowed to remove the silence on this user!";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'silself':
|
|
||||||
text = 'Why would you even try to silence yourself?';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'delerr':
|
|
||||||
text = "You aren't allowed to delete this message!";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'notban':
|
|
||||||
text = "{0} isn't banned!".replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'whoerr':
|
|
||||||
text = '{0} does not exist!'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'join':
|
|
||||||
text = '{0} joined.'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'jchan':
|
|
||||||
text = '{0} joined the channel.'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'leave':
|
|
||||||
text = '{0} left.'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'timeout':
|
|
||||||
text = '{0} exploded.'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'lchan':
|
|
||||||
text = '{0} left the channel.'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'kick':
|
|
||||||
text = '{0} got kicked.'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'nick':
|
|
||||||
text = '{0} changed their name to {1}.'.replace('{0}', parts[2]).replace('{1}', parts[3]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'crchan':
|
|
||||||
text = '{0} has been created.'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'delchan':
|
|
||||||
text = '{0} has been deleted.'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'cpwdchan':
|
|
||||||
text = 'Changed the channel password!';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'cprivchan':
|
|
||||||
text = 'Change access level of the channel!';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'ipaddr':
|
|
||||||
text = 'IP of {0}: {1}'.replace('{0}', parts[2]).replace('{1}', parts[3]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'cmdna':
|
|
||||||
text = "You aren't allowed to use '{0}'.".replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'nocmd':
|
|
||||||
text = "The command '{0}' does not exist.".replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'cmderr':
|
|
||||||
text = "You didn't format the command correctly!";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'usernf':
|
|
||||||
text = "{0} isn't logged in to the chat right now!".replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'kickna':
|
|
||||||
text = "You aren't allowed to kick {0}!".replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'samechan':
|
|
||||||
text = 'You are already in {0}!'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'ipchan':
|
|
||||||
case 'nochan':
|
|
||||||
text = "{0} doesn't exist!".replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'nopwchan':
|
|
||||||
text = "{0} has a password! Use '/join {0} [password]'.".replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'ipwchan':
|
|
||||||
text = "Wrong password! Couldn't join {0}.".replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'inchan':
|
|
||||||
text = "Channel names can't start with @ or *!";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'nischan':
|
|
||||||
text = '{0} already exists!'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'ndchan':
|
|
||||||
text = "You aren't allowed to delete {0}!".replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'namchan':
|
|
||||||
text = "You aren't allowed to edit {0}!".replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'nameinuse':
|
|
||||||
text = '{0} is currently taken!'.replace('{0}', parts[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'rankerr':
|
|
||||||
text = "You can't set the access level of a channel higher than your own!";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'reconnect':
|
|
||||||
text = 'Connection lost! Attempting to reconnect...';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'generr':
|
|
||||||
text = 'Something happened.';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'say':
|
|
||||||
default:
|
|
||||||
text = parts[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
return text;
|
|
||||||
};
|
|
||||||
|
|
||||||
const unfuckText = function(text) {
|
const unfuckText = function(text) {
|
||||||
const elem = document.createElement('div');
|
const elem = document.createElement('div');
|
||||||
elem.innerHTML = text.replace(/ <br\/> /g, "\n");
|
elem.innerHTML = text.replace(/ <br\/> /g, "\n");
|
||||||
|
@ -437,9 +214,6 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
startKeepAlive();
|
startKeepAlive();
|
||||||
|
|
||||||
if(settings.get('playSoundOnConnect'))
|
|
||||||
Umi.Sound.Play('join');
|
|
||||||
} else {
|
} else {
|
||||||
switch (data[2]) {
|
switch (data[2]) {
|
||||||
case 'joinfail':
|
case 'joinfail':
|
||||||
|
@ -496,25 +270,13 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Umi.Messages.Add(new Umi.Message(
|
Umi.Messages.Add(new Umi.Message(
|
||||||
data[6],
|
data[6], data[1], chatBot, '', channelName, false,
|
||||||
data[1],
|
{ type: 'join', isError: false, args: [juser.getName()], target: juser }
|
||||||
chatBot,
|
|
||||||
'{0} joined.'.replace('{0}', juser.getName()),
|
|
||||||
channelName,
|
|
||||||
false,
|
|
||||||
{
|
|
||||||
type: 'join',
|
|
||||||
isError: false,
|
|
||||||
args: [juser.getName()],
|
|
||||||
target: juser,
|
|
||||||
}
|
|
||||||
));
|
));
|
||||||
Umi.Sound.Play('join');
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '2': // message
|
case '2': // message
|
||||||
let text = data[3],
|
let text = data[3];
|
||||||
sound = 'incoming';
|
|
||||||
const muser = Umi.Users.Get(data[2]) || chatBot,
|
const muser = Umi.Users.Get(data[2]) || chatBot,
|
||||||
textParts = text.split("\f");
|
textParts = text.split("\f");
|
||||||
isPM = data[5][4] !== '0',
|
isPM = data[5][4] !== '0',
|
||||||
|
@ -526,16 +288,9 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
|
||||||
text = unfuckText(text);
|
text = unfuckText(text);
|
||||||
|
|
||||||
if(isBot) {
|
if(isBot) {
|
||||||
sound = 'server';
|
|
||||||
botInfo.isError = textParts[0] !== '0';
|
botInfo.isError = textParts[0] !== '0';
|
||||||
botInfo.type = textParts[1];
|
botInfo.type = textParts[1];
|
||||||
botInfo.args = textParts.slice(2);
|
botInfo.args = textParts.slice(2);
|
||||||
text = parseBotMessage(textParts);
|
|
||||||
|
|
||||||
if(botInfo.isError)
|
|
||||||
sound = 'error';
|
|
||||||
else if(textParts[1] === 'unban')
|
|
||||||
sound = 'unban';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isPM) {
|
if(isPM) {
|
||||||
|
@ -545,92 +300,27 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
|
||||||
text = tmpMsg.join(' ');
|
text = tmpMsg.join(' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(muser.getName() !== pmUserName)
|
|
||||||
sound = 'private';
|
|
||||||
|
|
||||||
if(Umi.Channels.Get(pmChannel) === null)
|
if(Umi.Channels.Get(pmChannel) === null)
|
||||||
Umi.Channels.Add(new Umi.Channel(pmChannel, false, true, true));
|
Umi.Channels.Add(new Umi.Channel(pmChannel, false, true, true));
|
||||||
|
|
||||||
Umi.UI.Menus.Attention('channels');
|
Umi.UI.Menus.Attention('channels');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(muser.getId() === userId)
|
|
||||||
sound = 'outgoing';
|
|
||||||
|
|
||||||
if(settings.get('playJokeSounds'))
|
|
||||||
try {
|
|
||||||
const trigger = mami.textTriggers.getTrigger(text);
|
|
||||||
if(trigger.isSoundType()) {
|
|
||||||
sound = '';
|
|
||||||
mami.sound.library.play(
|
|
||||||
trigger.getRandomSoundName(),
|
|
||||||
trigger.getVolume(),
|
|
||||||
trigger.getRate()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch(ex) {}
|
|
||||||
|
|
||||||
Umi.Messages.Add(new Umi.Message(
|
Umi.Messages.Add(new Umi.Message(
|
||||||
data[4],
|
data[4], data[1], muser, text,
|
||||||
data[1],
|
|
||||||
muser,
|
|
||||||
text,
|
|
||||||
isPM ? pmChannel : (data[6] || channelName),
|
isPM ? pmChannel : (data[6] || channelName),
|
||||||
false,
|
false, botInfo, isAction
|
||||||
botInfo,
|
|
||||||
isAction
|
|
||||||
));
|
));
|
||||||
|
|
||||||
if(!settings.get('onlySoundOnMention') && sound !== '')
|
|
||||||
Umi.Sound.Play(sound);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '3': // leave
|
case '3': // leave
|
||||||
const luser = Umi.Users.Get(data[1]);
|
const luser = Umi.Users.Get(data[1]);
|
||||||
let ltext = '',
|
|
||||||
lsound = null;
|
|
||||||
|
|
||||||
switch(data[3]) {
|
|
||||||
case 'flood':
|
|
||||||
ltext = '{0} got kicked for flood protection.';
|
|
||||||
lsound = 'flood';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'timeout':
|
|
||||||
ltext = '{0} exploded.';
|
|
||||||
lsound = 'timeout';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'kick':
|
|
||||||
ltext = '{0} got bludgeoned to death.';
|
|
||||||
lsound = 'kick';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'leave':
|
|
||||||
default:
|
|
||||||
ltext = '{0} left.';
|
|
||||||
lsound = 'leave';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Umi.Messages.Add(new Umi.Message(
|
Umi.Messages.Add(new Umi.Message(
|
||||||
data[5],
|
data[5], data[4], chatBot, '', channelName, false,
|
||||||
data[4],
|
{ type: data[3], isError: false, args: [luser.getName()], target: luser }
|
||||||
chatBot,
|
|
||||||
ltext.replace('{0}', luser.getName()),
|
|
||||||
channelName,
|
|
||||||
false,
|
|
||||||
{
|
|
||||||
type: data[3],
|
|
||||||
isError: false,
|
|
||||||
args: [luser.getName()],
|
|
||||||
target: luser,
|
|
||||||
}
|
|
||||||
));
|
));
|
||||||
Umi.Users.Remove(luser);
|
Umi.Users.Remove(luser);
|
||||||
|
|
||||||
if(lsound !== null)
|
|
||||||
Umi.Sound.Play(lsound);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '4': // channel
|
case '4': // channel
|
||||||
|
@ -656,53 +346,25 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
|
||||||
case '5': // user move
|
case '5': // user move
|
||||||
switch(data[1]) {
|
switch(data[1]) {
|
||||||
case '0':
|
case '0':
|
||||||
const umuser = new Umi.User(data[2], data[3], data[4], data[5]),
|
const umuser = new Umi.User(data[2], data[3], data[4], data[5]);
|
||||||
text = '{0} joined the channel.';
|
|
||||||
|
|
||||||
Umi.Users.Add(umuser);
|
Umi.Users.Add(umuser);
|
||||||
Umi.Messages.Add(new Umi.Message(
|
Umi.Messages.Add(new Umi.Message(
|
||||||
data[6],
|
data[6], null, chatBot, '', channelName, false,
|
||||||
null,
|
{ type: 'jchan', isError: false, args: [ umuser.getName() ], target: umuser }
|
||||||
chatBot,
|
|
||||||
text.replace('{0}', umuser.getName()),
|
|
||||||
channelName,
|
|
||||||
false,
|
|
||||||
{
|
|
||||||
type: 'jchan',
|
|
||||||
isError: false,
|
|
||||||
args: [
|
|
||||||
umuser.getName()
|
|
||||||
],
|
|
||||||
target: umuser,
|
|
||||||
}
|
|
||||||
));
|
));
|
||||||
Umi.Sound.Play('join');
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '1':
|
case '1':
|
||||||
if(data[2] === userId)
|
if(data[2] === userId)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const mouser = Umi.Users.Get(+data[2]),
|
const mouser = Umi.Users.Get(+data[2]);
|
||||||
motext = '{0} has left the channel.';
|
|
||||||
|
|
||||||
Umi.Messages.Add(new Umi.Message(
|
Umi.Messages.Add(new Umi.Message(
|
||||||
data[3],
|
data[3], null, chatBot, '', channelName, false,
|
||||||
null,
|
{ type: 'lchan', isError: false, args: [ mouser.getName() ], target: mouser }
|
||||||
chatBot,
|
|
||||||
motext.replace('{0}', mouser.getName()),
|
|
||||||
channelName,
|
|
||||||
false,
|
|
||||||
{
|
|
||||||
type: 'lchan',
|
|
||||||
isError: false,
|
|
||||||
args: [
|
|
||||||
mouser.getName()
|
|
||||||
],
|
|
||||||
target: mouser,
|
|
||||||
}
|
|
||||||
));
|
));
|
||||||
Umi.Sound.Play('leave');
|
|
||||||
Umi.Users.Remove(mouser);
|
Umi.Users.Remove(mouser);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -737,8 +399,6 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
|
||||||
cmtextParts = cmtext.split("\f"),
|
cmtextParts = cmtext.split("\f"),
|
||||||
cmbotInfo = {};
|
cmbotInfo = {};
|
||||||
|
|
||||||
cmtext = unfuckText(cmtext);
|
|
||||||
|
|
||||||
if(isNaN(cmid))
|
if(isNaN(cmid))
|
||||||
cmid = -Math.ceil(Math.random() * 10000000000);
|
cmid = -Math.ceil(Math.random() * 10000000000);
|
||||||
|
|
||||||
|
@ -746,18 +406,13 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
|
||||||
cmbotInfo.isError = cmtextParts[0] !== '0';
|
cmbotInfo.isError = cmtextParts[0] !== '0';
|
||||||
cmbotInfo.type = cmtextParts[1];
|
cmbotInfo.type = cmtextParts[1];
|
||||||
cmbotInfo.args = cmtextParts.slice(2);
|
cmbotInfo.args = cmtextParts.slice(2);
|
||||||
cmtext = parseBotMessage(cmtextParts);
|
cmtext = '';
|
||||||
}
|
} else
|
||||||
|
cmtext = unfuckText(cmtext);
|
||||||
|
|
||||||
Umi.Messages.Add(new Umi.Message(
|
Umi.Messages.Add(new Umi.Message(
|
||||||
cmid,
|
cmid, data[2], cmuser, cmtext, channelName, false, cmbotInfo,
|
||||||
data[2],
|
cmflags[1] !== '0' && cmflags[3] === '0', true
|
||||||
cmuser,
|
|
||||||
cmtext,
|
|
||||||
channelName,
|
|
||||||
false,
|
|
||||||
cmbotInfo,
|
|
||||||
cmflags[1] !== '0' && cmflags[3] === '0',
|
|
||||||
));
|
));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -830,7 +485,6 @@ Umi.Protocol.SockChat.Protocol = function(views, settings) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let icon, header;
|
let icon, header;
|
||||||
if(isBan) {
|
if(isBan) {
|
||||||
icon = 'hammer';
|
icon = 'hammer';
|
||||||
|
|
|
@ -8,7 +8,8 @@ const MamiSoundContext = function() {
|
||||||
const manager = new MamiSoundManager(audioCtx);
|
const manager = new MamiSoundManager(audioCtx);
|
||||||
const library = new MamiSoundLibrary(manager);
|
const library = new MamiSoundLibrary(manager);
|
||||||
const packs = new MamiSoundPacks;
|
const packs = new MamiSoundPacks;
|
||||||
const packPlayer = new MamiSoundPackPlayer(library);
|
|
||||||
|
let pack = new MamiSoundPack;
|
||||||
|
|
||||||
const pub = {};
|
const pub = {};
|
||||||
|
|
||||||
|
@ -17,7 +18,16 @@ const MamiSoundContext = function() {
|
||||||
manager: { value: manager, enumerable: true },
|
manager: { value: manager, enumerable: true },
|
||||||
library: { value: library, enumerable: true },
|
library: { value: library, enumerable: true },
|
||||||
packs: { value: packs, enumerable: true },
|
packs: { value: packs, enumerable: true },
|
||||||
packPlayer: { value: packPlayer, enumerable: true },
|
|
||||||
|
pack: {
|
||||||
|
get: () => pack,
|
||||||
|
set: value => {
|
||||||
|
if(typeof value !== 'object' || typeof value.getEventSound !== 'function')
|
||||||
|
throw 'value is not a valid soundpack';
|
||||||
|
pack = value;
|
||||||
|
},
|
||||||
|
enumerable: true,
|
||||||
|
},
|
||||||
|
|
||||||
ready: { get: audioCtx.isReady, enumerable: true },
|
ready: { get: audioCtx.isReady, enumerable: true },
|
||||||
volume: { get: audioCtx.getVolume, set: audioCtx.setVolume, enumerable: true },
|
volume: { get: audioCtx.getVolume, set: audioCtx.setVolume, enumerable: true },
|
||||||
|
|
|
@ -78,6 +78,9 @@ const MamiSoundLibrary = function(soundMgr) {
|
||||||
loadBuffer: async name => await soundMgr.loadBuffer(getSoundSources(name)),
|
loadBuffer: async name => await soundMgr.loadBuffer(getSoundSources(name)),
|
||||||
loadSource: loadSoundSource,
|
loadSource: loadSoundSource,
|
||||||
play: async (name, volume, rate) => {
|
play: async (name, volume, rate) => {
|
||||||
|
if(typeof name !== 'string')
|
||||||
|
return;
|
||||||
|
|
||||||
const source = await loadSoundSource(name);
|
const source = await loadSoundSource(name);
|
||||||
|
|
||||||
if(typeof volume === 'number')
|
if(typeof volume === 'number')
|
||||||
|
|
|
@ -6,6 +6,8 @@ const MamiSoundPack = function(name, isReadOnly, title, events) {
|
||||||
title = (title || '').toString();
|
title = (title || '').toString();
|
||||||
events = events || new Map;
|
events = events || new Map;
|
||||||
|
|
||||||
|
const hasEventSound = eventName => events.has(eventName);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getName: () => name,
|
getName: () => name,
|
||||||
isReadOnly: () => isReadOnly,
|
isReadOnly: () => isReadOnly,
|
||||||
|
@ -16,11 +18,24 @@ const MamiSoundPack = function(name, isReadOnly, title, events) {
|
||||||
title = (newTitle || '').toString();
|
title = (newTitle || '').toString();
|
||||||
},
|
},
|
||||||
getEventNames: () => Array.from(events.keys()),
|
getEventNames: () => Array.from(events.keys()),
|
||||||
hasEventSound: eventName => events.has(eventName),
|
hasEventSound: hasEventSound,
|
||||||
getEventSound: eventName => {
|
getEventSound: eventNames => {
|
||||||
if(!events.has(eventName))
|
let event;
|
||||||
throw 'event not registered';
|
|
||||||
return events.get(eventName);
|
if(Array.isArray(eventNames)) {
|
||||||
|
for(const name of eventNames)
|
||||||
|
if(hasEventSound(name)) {
|
||||||
|
event = name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if(hasEventSound(eventNames)) {
|
||||||
|
event = eventNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(event === undefined)
|
||||||
|
return;
|
||||||
|
|
||||||
|
return events.get(event);
|
||||||
},
|
},
|
||||||
setEventSound: (eventName, soundName) => {
|
setEventSound: (eventName, soundName) => {
|
||||||
events.set(
|
events.set(
|
||||||
|
@ -40,47 +55,6 @@ const MamiSoundPack = function(name, isReadOnly, title, events) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const MamiSoundPackPlayer = function(sndLibrary) {
|
|
||||||
let pack;
|
|
||||||
|
|
||||||
return {
|
|
||||||
loadPack: packInfo => {
|
|
||||||
if(typeof packInfo !== 'object' || typeof packInfo.getEventSound !== 'function')
|
|
||||||
throw 'pack is not a valid soundpack';
|
|
||||||
pack = packInfo;
|
|
||||||
},
|
|
||||||
unloadPack: () => {
|
|
||||||
pack = undefined;
|
|
||||||
buffers.clear();
|
|
||||||
},
|
|
||||||
hasPack: () => pack !== undefined,
|
|
||||||
|
|
||||||
hasEvent: name => pack !== undefined && pack.hasEventSound(event),
|
|
||||||
playEvent: async event => {
|
|
||||||
if(pack === undefined)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(Array.isArray(event)) {
|
|
||||||
const names = event;
|
|
||||||
event = undefined;
|
|
||||||
|
|
||||||
for(const name of names) {
|
|
||||||
if(pack.hasEventSound(name)) {
|
|
||||||
event = name;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(event === undefined)
|
|
||||||
return;
|
|
||||||
} else if(!pack.hasEventSound(event))
|
|
||||||
return;
|
|
||||||
|
|
||||||
await sndLibrary.play(pack.getEventSound(event));
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const MamiSoundPacks = function() {
|
const MamiSoundPacks = function() {
|
||||||
const packs = new Map;
|
const packs = new Map;
|
||||||
|
|
||||||
|
|
|
@ -1,124 +1,109 @@
|
||||||
#include sound/seinfeld.js
|
#include sound/seinfeld.js
|
||||||
|
|
||||||
Umi.Sound = (() => {
|
Umi.Sound = (() => {
|
||||||
return {
|
const getLibrarySound = event => {
|
||||||
Play: sound => {
|
if(!event || event === 'none')
|
||||||
if(!sound || sound === 'none')
|
return;
|
||||||
|
|
||||||
|
const minecraft = mami.settings.get('minecraft');
|
||||||
|
|
||||||
|
if(event === 'join') {
|
||||||
|
if(!mami.settings.get('soundEnableJoin'))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch(sound) {
|
if(mami.settings.get('seinfeld'))
|
||||||
case 'join':
|
return Seinfeld.getRandom();
|
||||||
if(!mami.settings.get('soundEnableJoin'))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(mami.settings.get('seinfeld')) {
|
if(minecraft === 'yes')
|
||||||
mami.sound.library.play(Seinfeld.getRandom());
|
return 'minecraft:door:open';
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(mami.settings.get('minecraft')) {
|
if(minecraft === 'old')
|
||||||
case 'yes':
|
return 'minecraft:door:open-old';
|
||||||
mami.sound.library.play('minecraft:door:open');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'old':
|
return mami.sound.pack.getEventSound('join');
|
||||||
mami.sound.library.play('minecraft:door:open-old');
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
if(event === 'leave') {
|
||||||
mami.sound.packPlayer.playEvent('join');
|
if(!mami.settings.get('soundEnableLeave'))
|
||||||
break;
|
return;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'leave':
|
if(minecraft === 'yes')
|
||||||
if(!mami.settings.get('soundEnableLeave'))
|
return 'minecraft:door:close';
|
||||||
return;
|
|
||||||
|
|
||||||
switch(mami.settings.get('minecraft')) {
|
if(minecraft === 'old')
|
||||||
case 'yes':
|
return 'minecraft:door:close-old';
|
||||||
mami.sound.library.play('minecraft:door:close');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'old':
|
return mami.sound.pack.getEventSound('leave');
|
||||||
mami.sound.library.play('minecraft:door:close-old');
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
if(event === 'error') {
|
||||||
mami.sound.packPlayer.playEvent('leave');
|
if(!mami.settings.get('soundEnableError'))
|
||||||
break;
|
return;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'error':
|
return mami.sound.pack.getEventSound('error');
|
||||||
if(!mami.settings.get('soundEnableError'))
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
mami.sound.packPlayer.playEvent('error');
|
if(event === 'server') {
|
||||||
break;
|
if(!mami.settings.get('soundEnableServer'))
|
||||||
|
return;
|
||||||
|
|
||||||
case 'server':
|
return mami.sound.pack.getEventSound('server');
|
||||||
if(!mami.settings.get('soundEnableServer'))
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
mami.sound.packPlayer.playEvent('server');
|
if(event === 'unban') {
|
||||||
break;
|
if(!mami.settings.get('soundEnableServer'))
|
||||||
|
return;
|
||||||
|
|
||||||
case 'unban':
|
return mami.sound.pack.getEventSound(['unban', 'server']);
|
||||||
if(!mami.settings.get('soundEnableServer'))
|
}
|
||||||
return;
|
|
||||||
|
|
||||||
mami.sound.packPlayer.playEvent(['unban', 'server']);
|
if(event === 'incoming') {
|
||||||
break;
|
if(!mami.settings.get('soundEnableIncoming'))
|
||||||
|
return;
|
||||||
|
|
||||||
case 'incoming':
|
if(mami.settings.get('windowsLiveMessenger'))
|
||||||
if(!mami.settings.get('soundEnableIncoming'))
|
return 'msn:incoming';
|
||||||
return;
|
|
||||||
|
|
||||||
if(mami.settings.get('windowsLiveMessenger')) {
|
return mami.sound.pack.getEventSound('incoming');
|
||||||
mami.sound.library.play('msn:incoming');
|
}
|
||||||
} else {
|
|
||||||
mami.sound.packPlayer.playEvent('incoming');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'outgoing':
|
if(event === 'outgoing') {
|
||||||
if(!mami.settings.get('soundEnableOutgoing'))
|
if(!mami.settings.get('soundEnableOutgoing'))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mami.sound.packPlayer.playEvent('outgoing');
|
return mami.sound.pack.getEventSound('outgoing');
|
||||||
break;
|
}
|
||||||
|
|
||||||
case 'private':
|
if(event === 'private' || event === 'incoming-priv') {
|
||||||
case 'incoming-priv':
|
if(!mami.settings.get('soundEnablePrivate'))
|
||||||
if(!mami.settings.get('soundEnablePrivate'))
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
mami.sound.packPlayer.playEvent(['incoming-priv', 'incoming']);
|
return mami.sound.pack.getEventSound(['incoming-priv', 'incoming']);
|
||||||
break;
|
}
|
||||||
|
|
||||||
case 'flood':
|
if(event === 'flood') {
|
||||||
if(!mami.settings.get('soundEnableForceLeave'))
|
if(!mami.settings.get('soundEnableForceLeave'))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mami.sound.packPlayer.playEvent(['flood', 'kick', 'leave']);
|
return mami.sound.pack.getEventSound(['flood', 'kick', 'leave']);
|
||||||
break;
|
}
|
||||||
|
|
||||||
case 'timeout':
|
if(event === 'timeout') {
|
||||||
if(!mami.settings.get('soundEnableForceLeave'))
|
if(!mami.settings.get('soundEnableForceLeave'))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mami.sound.packPlayer.playEvent(['timeout', 'leave']);
|
return mami.sound.pack.getEventSound(['timeout', 'leave']);
|
||||||
break;
|
}
|
||||||
|
|
||||||
case 'kick':
|
if(event === 'kick' || event === 'forceLeave') {
|
||||||
case 'forceLeave':
|
if(!mami.settings.get('soundEnableForceLeave'))
|
||||||
if(!mami.settings.get('soundEnableForceLeave'))
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
mami.sound.packPlayer.playEvent(['kick', 'leave']);
|
return mami.sound.pack.getEventSound(['kick', 'leave']);
|
||||||
break;
|
}
|
||||||
}
|
};
|
||||||
},
|
|
||||||
|
return {
|
||||||
|
Convert: getLibrarySound,
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#include channels.js
|
#include channels.js
|
||||||
#include common.js
|
#include common.js
|
||||||
#include server.js
|
#include server.js
|
||||||
#include title.js
|
|
||||||
#include user.js
|
#include user.js
|
||||||
#include utility.js
|
#include utility.js
|
||||||
#include sound/umisound.js
|
#include sound/umisound.js
|
||||||
|
@ -13,76 +12,6 @@
|
||||||
Umi.UI.Hooks = (function() {
|
Umi.UI.Hooks = (function() {
|
||||||
return {
|
return {
|
||||||
AddHooks: function() {
|
AddHooks: function() {
|
||||||
const title = new MamiWindowTitle({
|
|
||||||
getName: () => futami.get('title'),
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener('focus', function() {
|
|
||||||
title.clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
Umi.Messages.OnRemove.push(function(msg) {
|
|
||||||
Umi.UI.Messages.Remove(msg);
|
|
||||||
});
|
|
||||||
|
|
||||||
Umi.Messages.OnClear.push(function() {
|
|
||||||
Umi.UI.Messages.RemoveAll();
|
|
||||||
});
|
|
||||||
|
|
||||||
Umi.Messages.OnAdd.push(function(msg) {
|
|
||||||
Umi.UI.Channels.Unread(msg.getChannel());
|
|
||||||
Umi.UI.Messages.Add(msg);
|
|
||||||
|
|
||||||
if(!document.hidden)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(mami.settings.get('flashTitle')) {
|
|
||||||
let titleText = ' ' + msg.getUser().getName(),
|
|
||||||
channel = Umi.Channels.Current() || null;
|
|
||||||
if(msg.getUser().isBot() && mami.settings.get('showServerMsgInTitle'))
|
|
||||||
titleText = ' ' + msg.getText();
|
|
||||||
|
|
||||||
if(channel !== null && channel.getName() !== msg.getChannel())
|
|
||||||
titleText += ' @ ' + channel.getName();
|
|
||||||
|
|
||||||
title.strobe([
|
|
||||||
`[ @] ${titleText}`,
|
|
||||||
`[@ ] ${titleText}`,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mami.settings.get('enableNotifications') && Umi.User.getCurrentUser() !== null) {
|
|
||||||
const triggers = (mami.settings.get('notificationTriggers') || '').toLowerCase().split(' '),
|
|
||||||
options = {};
|
|
||||||
|
|
||||||
triggers.push((Umi.User.getCurrentUser() || { getName: function() { return ''; } }).getName().toLowerCase());
|
|
||||||
options.body = 'Click here to see what they said.';
|
|
||||||
|
|
||||||
if(mami.settings.get('notificationShowMessage'))
|
|
||||||
options.body += "\n" + msg.getText();
|
|
||||||
|
|
||||||
const avatarUrl = futami.get('avatar');
|
|
||||||
if(avatarUrl.length > 0)
|
|
||||||
options.icon = avatarUrl.replace('{user:id}', msg.getUser().getId()).replace('{resolution}', '80').replace('{user:avatar_change}', msg.getUser().getAvatarTime().toString());
|
|
||||||
|
|
||||||
for(const trigger of triggers) {
|
|
||||||
const message = ' ' + msg.getText() + ' ';
|
|
||||||
|
|
||||||
if(trigger.trim() === '')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if(message.toLowerCase().indexOf(' ' + trigger + ' ') >= 0) {
|
|
||||||
new Notification('{0} mentioned you!'.replace('{0}', msg.getUser().getName()), options);
|
|
||||||
if(mami.settings.get('onlySoundOnMention'))
|
|
||||||
Umi.Sound.Play('incoming');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
Umi.Users.OnAdd.push(function(user) {
|
Umi.Users.OnAdd.push(function(user) {
|
||||||
Umi.UI.Users.Add(user);
|
Umi.UI.Users.Add(user);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,48 +1,155 @@
|
||||||
#include channels.js
|
#include channels.js
|
||||||
#include common.js
|
#include common.js
|
||||||
#include parsing.js
|
#include parsing.js
|
||||||
|
#include title.js
|
||||||
|
#include txtrigs.js
|
||||||
#include url.js
|
#include url.js
|
||||||
#include users.js
|
#include users.js
|
||||||
#include utility.js
|
#include utility.js
|
||||||
#include weeb.js
|
#include weeb.js
|
||||||
|
#include sound/umisound.js
|
||||||
#include ui/emotes.js
|
#include ui/emotes.js
|
||||||
|
|
||||||
Umi.UI.Messages = (function() {
|
Umi.UI.Messages = (function() {
|
||||||
let lastMsgUser = null,
|
let forceUserInfo = false,
|
||||||
|
lastMsgUser = null,
|
||||||
lastMsgChannel = null,
|
lastMsgChannel = null,
|
||||||
lastWasTiny = null;
|
lastWasTiny = null;
|
||||||
|
|
||||||
|
const title = new MamiWindowTitle({
|
||||||
|
getName: () => futami.get('title'),
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('focus', function() {
|
||||||
|
title.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
const botMsgs = {
|
||||||
|
'say': { text: '%0' },
|
||||||
|
'generr': { text: 'Something unexpected happened.' },
|
||||||
|
'flwarn': { text: 'You are about to hit the flood limit! If you continue you will be kicked.' },
|
||||||
|
'unban': { text: '%0 is no longer banned.', sound: 'unban' },
|
||||||
|
'delerr': { text: 'You are not allowed to delete this message.' },
|
||||||
|
'notban': { text: '%0 is not banned.' },
|
||||||
|
'whoerr': { text: '%0 does not exist.' },
|
||||||
|
'join': { text: '%0 has joined.', action: 'has joined', sound: 'join' },
|
||||||
|
'leave': { text: '%0 has disconnected.', action: 'has disconnected', avatar: 'greyscale', sound: 'leave' },
|
||||||
|
'jchan': { text: '%0 has joined the channel.', action: 'has joined the channel', sound: 'join' },
|
||||||
|
'lchan': { text: '%0 has left the channel.', action: 'has left the channel', avatar: 'greyscale', sound: 'leave' },
|
||||||
|
'kick': { text: '%0 got bludgeoned to death.', action: 'got bludgeoned to death', avatar: 'invert', sound: 'kick' },
|
||||||
|
'flood': { text: '%0 got kicked for flood protection.', action: 'got kicked for flood protection', avatar: 'invert', sound: 'flood' },
|
||||||
|
'timeout': { text: '%0 exploded.', action: 'exploded', avatar: 'greyscale', sound: 'timeout' },
|
||||||
|
'nick': { text: '%0 changed their name to %1.' },
|
||||||
|
'crchan': { text: 'Channel %0 has been created.' },
|
||||||
|
'delchan': { text: 'Channel %0 has been deleted.' },
|
||||||
|
'cpwdchan': { text: 'Channel password has been changed.' },
|
||||||
|
'cprivchan': { text: 'Channel access level has been changed.' },
|
||||||
|
'ipaddr': { text: 'IP address of %0 is %1.' },
|
||||||
|
'cmdna': { text: 'You are not allowed to use %0.' },
|
||||||
|
'nocmd': { text: 'Command %0 does not exist.' },
|
||||||
|
'cmderr': { text: 'You did not use that command correctly.' },
|
||||||
|
'usernf': { text: '%0 is not logged in right now!' },
|
||||||
|
'kickna': { text: 'You are not allowed to kick %0.' },
|
||||||
|
'samechan': { text: 'You are already in channel %0.' },
|
||||||
|
'ipchan': { text: 'You are not allowed to join channel %0.' },
|
||||||
|
'nochan': { text: 'Channel %0 does not exist.' },
|
||||||
|
'nopwchan': { text: 'Channel %0 requires a password. Use /join %0 <password>' },
|
||||||
|
'ipwchan': { text: 'Wrong password for channel %0.' },
|
||||||
|
'inchan': { text: 'Channel name contains invalid characters.' },
|
||||||
|
'nischan': { text: 'A channel with the name %0 already exists.' },
|
||||||
|
'ndchan': { text: 'You are not allowed to deleted channel %0.' },
|
||||||
|
'namchan': { text: 'You are not allowed to edit channel %0.' },
|
||||||
|
'nameinuse': { text: 'Someone else is already using the name %0.' },
|
||||||
|
'rankerr': { text: 'You cannot set the access level of a channel higher than that of your own.' },
|
||||||
|
'banlist': {
|
||||||
|
text: 'Banned: %0',
|
||||||
|
filter: args => {
|
||||||
|
const bans = args[0].split(', ');
|
||||||
|
for(const i in bans)
|
||||||
|
bans[i] = bans[i].slice(92, -4);
|
||||||
|
|
||||||
|
args[0] = bans.join(', ');
|
||||||
|
return args;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'who': {
|
||||||
|
text: 'Online: %0',
|
||||||
|
filter: args => {
|
||||||
|
const users = args[0].split(', ');
|
||||||
|
for(const i in users) {
|
||||||
|
const isSelf = users[i].includes(' style="font-weight: bold;"');
|
||||||
|
users[i] = users[i].slice(isSelf ? 102 : 75, -4);
|
||||||
|
if(isSelf) users[i] += ' (You)';
|
||||||
|
}
|
||||||
|
|
||||||
|
args[0] = users.join(', ');
|
||||||
|
return args;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'whochan': {
|
||||||
|
text: 'Online in %0: %1',
|
||||||
|
filter: args => {
|
||||||
|
const users = args[1].split(', ');
|
||||||
|
for(const i in users) {
|
||||||
|
const isSelf = users[i].includes(' style="font-weight: bold;"');
|
||||||
|
users[i] = users[i].slice(isSelf ? 102 : 75, -4);
|
||||||
|
if(isSelf) users[i] += ' (You)';
|
||||||
|
}
|
||||||
|
|
||||||
|
args[1] = users.join(', ');
|
||||||
|
return args;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatTemplate = (template, args) => {
|
||||||
|
if(typeof template !== 'string')
|
||||||
|
template = '';
|
||||||
|
|
||||||
|
if(Array.isArray(args))
|
||||||
|
for(let i = 0; i < args.length; ++i) {
|
||||||
|
const arg = args[i] === undefined || args[i] === null ? '' : args[i].toString();
|
||||||
|
template = template.replace(new RegExp(`%${i}`, 'g'), arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return template;
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
Add: function(msg) {
|
Add: function(msg) {
|
||||||
if(msg.getChannel() !== null
|
const currentChannel = Umi.Channels.Current();
|
||||||
&& Umi.Channels.Current() !== null
|
const channelName = msg.getChannel();
|
||||||
&& msg.getChannel() !== Umi.Channels.Current().getName())
|
const sender = msg.getUser();
|
||||||
return;
|
const isOutgoing = Umi.User.isCurrentUser(sender);
|
||||||
|
const hasSeen = msg.hasSeen();
|
||||||
|
const displayMessage = currentChannel === null || channelName === null || channelName === currentChannel.getName();
|
||||||
|
const notifyPM = !displayMessage && !isOutgoing && !hasSeen && channelName.startsWith('@');
|
||||||
|
|
||||||
let isTiny = false,
|
let isTiny = false,
|
||||||
skipTextParsing = false,
|
skipTextParsing = false,
|
||||||
msgText = msg.getText();
|
msgText = msg.getText(),
|
||||||
|
msgTextLong = msgText;
|
||||||
|
|
||||||
let eBase = null,
|
let eBase, eAvatar, eText, eMeta, eUser;
|
||||||
eAvatar = null,
|
|
||||||
eText = null,
|
|
||||||
eMeta = null,
|
|
||||||
eUser = null;
|
|
||||||
|
|
||||||
const sender = msg.getUser();
|
|
||||||
let avatarUser = sender,
|
let avatarUser = sender,
|
||||||
avatarSize = '80';
|
avatarSize = '80';
|
||||||
|
|
||||||
const userClass = 'message--user-' + sender.getId();
|
let soundName = isOutgoing ? 'outgoing' : 'incoming',
|
||||||
|
soundVolume, soundRate, soundIsLegacy = true;
|
||||||
|
|
||||||
|
const userClass = `message--user-${sender.getId()}`;
|
||||||
|
|
||||||
const classes = ['message', userClass];
|
const classes = ['message', userClass];
|
||||||
const styles = {};
|
const styles = {};
|
||||||
|
|
||||||
const avatarClasses = ['message__avatar'];
|
const avatarClasses = ['message__avatar'];
|
||||||
|
|
||||||
const msgIsFirst = lastMsgUser !== sender.getId() || lastMsgChannel !== msg.getChannel();
|
const msgIsFirst = forceUserInfo || lastMsgUser !== sender.getId() || lastMsgChannel !== msg.getChannel();
|
||||||
if(msgIsFirst)
|
if(msgIsFirst) {
|
||||||
|
forceUserInfo = false;
|
||||||
classes.push('message--first');
|
classes.push('message--first');
|
||||||
|
}
|
||||||
|
|
||||||
if(msg.shouldHighlight())
|
if(msg.shouldHighlight())
|
||||||
classes.push('message--highlight');
|
classes.push('message--highlight');
|
||||||
|
@ -60,164 +167,231 @@ Umi.UI.Messages = (function() {
|
||||||
+ ':' + msgDateTimeObj.getMinutes().toString().padStart(2, '0')
|
+ ':' + msgDateTimeObj.getMinutes().toString().padStart(2, '0')
|
||||||
+ ':' + msgDateTimeObj.getSeconds().toString().padStart(2, '0');
|
+ ':' + msgDateTimeObj.getSeconds().toString().padStart(2, '0');
|
||||||
|
|
||||||
if(sender.isBot() && mami.settings.get('fancyInfo')) {
|
if(sender.isBot()) {
|
||||||
const botInfo = msg.getBotInfo();
|
const botInfo = msg.getBotInfo();
|
||||||
|
soundName = botInfo.isError ? 'error' : 'server';
|
||||||
|
|
||||||
if(botInfo) {
|
if(botMsgs.hasOwnProperty(botInfo.type)) {
|
||||||
if(botInfo.type === 'join' || botInfo.type === 'jchan'
|
const bmInfo = botMsgs[botInfo.type];
|
||||||
|| botInfo.type === 'leave' || botInfo.type === 'lchan'
|
|
||||||
|| botInfo.type === 'kick' || botInfo.type === 'flood'
|
let bArgs = botInfo.args;
|
||||||
|| botInfo.type === 'timeout') {
|
if(typeof bmInfo.filter === 'function')
|
||||||
const target = botInfo.target || Umi.Users.FindExact(botInfo.args[0]);
|
bArgs = bmInfo.filter(bArgs);
|
||||||
|
|
||||||
|
if(typeof bmInfo.sound === 'string')
|
||||||
|
soundName = bmInfo.sound;
|
||||||
|
|
||||||
|
let actionSuccess = false;
|
||||||
|
if(typeof bmInfo.action === 'string' && mami.settings.get('fancyInfo')) {
|
||||||
|
const target = botInfo.target || Umi.Users.FindExact(bArgs[0]);
|
||||||
|
|
||||||
if(target) {
|
if(target) {
|
||||||
|
actionSuccess = true;
|
||||||
isTiny = true;
|
isTiny = true;
|
||||||
skipTextParsing = true;
|
skipTextParsing = true;
|
||||||
avatarUser = target;
|
avatarUser = target;
|
||||||
msgText = 'did something';
|
|
||||||
|
|
||||||
$ari(classes, userClass);
|
$ari(classes, userClass);
|
||||||
|
|
||||||
switch(botInfo.type) {
|
msgText = bmInfo.action;
|
||||||
case 'join':
|
if(typeof bmInfo.avatar === 'string')
|
||||||
msgText = 'has joined';
|
avatarClasses.push(`avatar-filter-${bmInfo.avatar}`);
|
||||||
break;
|
}
|
||||||
case 'leave':
|
}
|
||||||
msgText = 'has disconnected';
|
|
||||||
avatarClasses.push('avatar-filter-greyscale');
|
msgTextLong = formatTemplate(bmInfo.text, bArgs);
|
||||||
break;
|
|
||||||
case 'jchan':
|
if(!actionSuccess)
|
||||||
msgText = 'has joined the channel';
|
msgText = msgTextLong;
|
||||||
break;
|
} else
|
||||||
case 'lchan':
|
msgText = msgTextLong = `!!! Received unsupported message type: ${botInfo.type} !!!`;
|
||||||
msgText = 'has left the channel';
|
} else {
|
||||||
avatarClasses.push('avatar-filter-greyscale');
|
if(mami.settings.get('playJokeSounds'))
|
||||||
break;
|
try {
|
||||||
case 'kick':
|
const trigger = mami.textTriggers.getTrigger(msgText);
|
||||||
msgText = 'got bludgeoned to death';
|
if(trigger.isSoundType()) {
|
||||||
avatarClasses.push('avatar-filter-invert');
|
soundIsLegacy = false;
|
||||||
break;
|
soundName = trigger.getRandomSoundName();
|
||||||
case 'flood':
|
soundVolume = trigger.getVolume();
|
||||||
msgText = 'got kicked for flood protection';
|
soundRate = trigger.getRate();
|
||||||
avatarClasses.push('avatar-filter-invert');
|
}
|
||||||
break;
|
} catch(ex) {}
|
||||||
case 'timeout':
|
}
|
||||||
msgText = 'exploded';
|
|
||||||
avatarClasses.push('avatar-filter-greyscale');
|
let avatarUrl = futami.get('avatar');
|
||||||
break;
|
if(typeof avatarUrl !== 'string' || avatarUrl.length < 1)
|
||||||
|
avatarUrl = undefined;
|
||||||
|
else
|
||||||
|
avatarUrl = avatarUrl.replace('{user:id}', avatarUser.getId())
|
||||||
|
.replace('{resolution}', avatarSize)
|
||||||
|
.replace('{user:avatar_change}', avatarUser.getAvatarTime().toString());
|
||||||
|
|
||||||
|
if(displayMessage) {
|
||||||
|
if(isTiny) {
|
||||||
|
if(!msgIsFirst) // small messages must always be "first"
|
||||||
|
classes.push('message--first');
|
||||||
|
classes.push('message-tiny');
|
||||||
|
|
||||||
|
avatarSize = '40';
|
||||||
|
|
||||||
|
if(msgText.indexOf("'") !== 0 || (msgText.match(/\'/g).length % 2) === 0)
|
||||||
|
msgText = "\xA0" + msgText;
|
||||||
|
|
||||||
|
eBase = <div id={`message-${msg.getId()}`} class={classes} style={styles}>
|
||||||
|
{eAvatar = <div class={avatarClasses}/>}
|
||||||
|
<div class="message__container">
|
||||||
|
{eMeta = <div class="message__meta">
|
||||||
|
{eUser = <div class="message__user" style={{ color: avatarUser.getColour() }}>{avatarUser.getName()}</div>}
|
||||||
|
{eText = <div class="message-tiny-text"/>}
|
||||||
|
<div class="message__time">{msgDateTime}</div>
|
||||||
|
</div>}
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
} else {
|
||||||
|
eBase = <div id={`message-${msg.getId()}`} class={classes} style={styles}>
|
||||||
|
{eAvatar = <div class={avatarClasses}/>}
|
||||||
|
<div class="message__container">
|
||||||
|
{eMeta = <div class="message__meta">
|
||||||
|
{eUser = <div class="message__user" style={{ color: avatarUser.getColour() }}>{avatarUser.getName()}</div>}
|
||||||
|
<div class="message__time">{msgDateTime}</div>
|
||||||
|
</div>}
|
||||||
|
{eText = <div class="message__text"/>}
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
eText.innerText = msgText;
|
||||||
|
|
||||||
|
if(!skipTextParsing) {
|
||||||
|
eText = Umi.UI.Emoticons.Parse(eText, msg);
|
||||||
|
eText = Umi.Parsing.Parse(eText, msg);
|
||||||
|
|
||||||
|
const urls = [];
|
||||||
|
|
||||||
|
if(mami.settings.get('autoParseUrls')) {
|
||||||
|
const textSplit = eText.innerText.split(' ');
|
||||||
|
for(const textPart of textSplit) {
|
||||||
|
const uri = Umi.URI.Parse(textPart);
|
||||||
|
|
||||||
|
if(uri !== null && uri.Slashes !== null) {
|
||||||
|
urls.push(textPart);
|
||||||
|
|
||||||
|
const anchorElem = <a class="markup__link" href={textPart} target="_blank" rel="nofollow noreferrer noopener">{textPart}</a>;
|
||||||
|
eText.innerHTML = eText.innerHTML.replace(textPart.replace(/&/g, '&'), anchorElem.outerHTML);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(isTiny) {
|
if(mami.settings.get('weeaboo')) {
|
||||||
if(!msgIsFirst) // small messages must always be "first"
|
eText.appendChild($t(Weeaboo.getTextSuffix(sender)));
|
||||||
classes.push('message--first');
|
|
||||||
classes.push('message-tiny');
|
|
||||||
|
|
||||||
avatarSize = '40';
|
const kaomoji = Weeaboo.getRandomKaomoji(true, msg);
|
||||||
|
if(kaomoji) {
|
||||||
if(msgText.indexOf("'") !== 0 || (msgText.match(/\'/g).length % 2) === 0)
|
eText.appendChild($t(' '));
|
||||||
msgText = "\xA0" + msgText;
|
eText.appendChild($t(kaomoji));
|
||||||
|
|
||||||
eBase = <div id={`message-${msg.getId()}`} class={classes} style={styles}>
|
|
||||||
{eAvatar = <div class={avatarClasses}/>}
|
|
||||||
<div class="message__container">
|
|
||||||
{eMeta = <div class="message__meta">
|
|
||||||
{eUser = <div class="message__user" style={{ color: avatarUser.getColour() }}>{avatarUser.getName()}</div>}
|
|
||||||
{eText = <div class="message-tiny-text"/>}
|
|
||||||
<div class="message__time">{msgDateTime}</div>
|
|
||||||
</div>}
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
} else {
|
|
||||||
eBase = <div id={`message-${msg.getId()}`} class={classes} style={styles}>
|
|
||||||
{eAvatar = <div class={avatarClasses}/>}
|
|
||||||
<div class="message__container">
|
|
||||||
{eMeta = <div class="message__meta">
|
|
||||||
{eUser = <div class="message__user" style={{ color: avatarUser.getColour() }}>{avatarUser.getName()}</div>}
|
|
||||||
<div class="message__time">{msgDateTime}</div>
|
|
||||||
</div>}
|
|
||||||
{eText = <div class="message__text"/>}
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
eText.innerText = msgText;
|
|
||||||
|
|
||||||
if(!skipTextParsing) {
|
|
||||||
eText = Umi.UI.Emoticons.Parse(eText, msg);
|
|
||||||
eText = Umi.Parsing.Parse(eText, msg);
|
|
||||||
|
|
||||||
const urls = [];
|
|
||||||
|
|
||||||
if(mami.settings.get('autoParseUrls')) {
|
|
||||||
const textSplit = eText.innerText.split(' ');
|
|
||||||
for(const textPart of textSplit) {
|
|
||||||
const uri = Umi.URI.Parse(textPart);
|
|
||||||
|
|
||||||
if(uri !== null && uri.Slashes !== null) {
|
|
||||||
urls.push(textPart);
|
|
||||||
|
|
||||||
const linkElement = $e({
|
|
||||||
tag: 'a',
|
|
||||||
attrs: {
|
|
||||||
className: 'markup__link',
|
|
||||||
href: textPart,
|
|
||||||
target: '_blank',
|
|
||||||
rel: 'nofollow noreferrer noopener',
|
|
||||||
},
|
|
||||||
child: textPart,
|
|
||||||
});
|
|
||||||
|
|
||||||
eText.innerHTML = eText.innerHTML.replace(textPart.replace(/&/g, '&'), linkElement.outerHTML);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(mami.settings.get('weeaboo'))
|
||||||
|
eUser.appendChild($t(Weeaboo.getNameSuffix(sender)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mami.settings.get('weeaboo')) {
|
if(isTiny !== lastWasTiny) {
|
||||||
eText.appendChild($t(Weeaboo.getTextSuffix(sender)));
|
if(!msgIsFirst)
|
||||||
|
eBase.classList.add('message--first');
|
||||||
|
eBase.classList.add(isTiny ? 'message-tiny-fix' : 'message-big-fix');
|
||||||
|
}
|
||||||
|
lastWasTiny = isTiny;
|
||||||
|
|
||||||
const kaomoji = Weeaboo.getRandomKaomoji(true, msg);
|
if(avatarUrl === undefined)
|
||||||
if(kaomoji) {
|
eAvatar.classList.add('message__avatar--disabled');
|
||||||
eText.appendChild($t(' '));
|
else
|
||||||
eText.appendChild($t(kaomoji));
|
eAvatar.style.backgroundImage = `url(${avatarUrl})`;
|
||||||
|
|
||||||
|
const msgsList = $i('umi-messages');
|
||||||
|
|
||||||
|
msgsList.appendChild(eBase);
|
||||||
|
lastMsgUser = sender.getId();
|
||||||
|
lastMsgChannel = msg.getChannel();
|
||||||
|
|
||||||
|
if(mami.settings.get('autoEmbedV1')) {
|
||||||
|
const callEmbedOn = eBase.querySelectorAll('a[onclick^="Umi.Parser.SockChatBBcode.Embed"]');
|
||||||
|
for(const embedElem of callEmbedOn)
|
||||||
|
if(embedElem.dataset.embed !== '1')
|
||||||
|
embedElem.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(mami.settings.get('autoScroll'))
|
||||||
|
msgsList.scrollTop = msgsList.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
let isMentioned = false;
|
||||||
|
const mentionTriggers = (mami.settings.get('notificationTriggers') || '').toLowerCase().split(' ');
|
||||||
|
const currentUser = Umi.User.getCurrentUser();
|
||||||
|
if(typeof currentUser === 'object' && typeof currentUser.getName === 'function')
|
||||||
|
mentionTriggers.push(currentUser.getName().toLowerCase());
|
||||||
|
|
||||||
|
const mentionText = ` ${msgTextLong} `.toLowerCase();
|
||||||
|
for(const trigger of mentionTriggers) {
|
||||||
|
if(trigger.trim() === '')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(mentionText.includes(` ${trigger} `)) {
|
||||||
|
isMentioned = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!isMentioned && mami.settings.get('onlySoundOnMention'))
|
||||||
|
soundName = undefined;
|
||||||
|
|
||||||
|
if(document.hidden) {
|
||||||
|
if(mami.settings.get('flashTitle')) {
|
||||||
|
let titleText = sender.isBot() && mami.settings.get('showServerMsgInTitle')
|
||||||
|
? ` ${msgTextLong}`
|
||||||
|
: ` ${sender.getName()}`;
|
||||||
|
|
||||||
|
// oops this won't work lol, we're filtering at the top
|
||||||
|
if(currentChannel !== null && currentChannel.getName() !== channelName)
|
||||||
|
titleText += ` @ ${channelName}`;
|
||||||
|
|
||||||
|
title.strobe([
|
||||||
|
`[ @] ${titleText}`,
|
||||||
|
`[@ ] ${titleText}`,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!hasSeen) {
|
||||||
|
Umi.UI.Channels.Unread(channelName);
|
||||||
|
|
||||||
|
if(mami.settings.get('enableNotifications') && isMentioned) {
|
||||||
|
const options = {};
|
||||||
|
|
||||||
|
options.body = 'Click here to see what they said.';
|
||||||
|
if(mami.settings.get('notificationShowMessage'))
|
||||||
|
options.body += "\n" + msgTextLong;
|
||||||
|
|
||||||
|
if(avatarUrl !== undefined)
|
||||||
|
options.icon = avatarUrl;
|
||||||
|
|
||||||
|
const notif = new Notification(`${sender.getName()} mentioned you!`, options);
|
||||||
|
notif.addEventListener('click', () => {
|
||||||
|
window.focus();
|
||||||
|
});
|
||||||
|
document.addEventListener('visibilitychange', () => {
|
||||||
|
if(document.visibilityState === 'visible')
|
||||||
|
notif.close();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mami.settings.get('weeaboo'))
|
|
||||||
eUser.appendChild($t(Weeaboo.getNameSuffix(sender)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isTiny !== lastWasTiny) {
|
if(soundName !== undefined && !hasSeen) {
|
||||||
if(!msgIsFirst)
|
if(soundIsLegacy)
|
||||||
eBase.classList.add('message--first');
|
soundName = Umi.Sound.Convert(soundName);
|
||||||
eBase.classList.add(isTiny ? 'message-tiny-fix' : 'message-big-fix');
|
|
||||||
|
mami.sound.library.play(soundName, soundVolume, soundRate);
|
||||||
}
|
}
|
||||||
lastWasTiny = isTiny;
|
|
||||||
|
|
||||||
const avatarUrl = futami.get('avatar');
|
|
||||||
if (avatarUrl !== null && avatarUrl.length > 1) {
|
|
||||||
eAvatar.style.backgroundImage = 'url({0})'.replace('{0}', avatarUrl.replace('{user:id}', avatarUser.getId())
|
|
||||||
.replace('{resolution}', avatarSize).replace('{user:avatar_change}', avatarUser.getAvatarTime().toString()));
|
|
||||||
} else eAvatar.classList.add('message__avatar--disabled');
|
|
||||||
|
|
||||||
const msgsList = $i('umi-messages');
|
|
||||||
|
|
||||||
msgsList.appendChild(eBase);
|
|
||||||
lastMsgUser = sender.getId();
|
|
||||||
lastMsgChannel = msg.getChannel();
|
|
||||||
|
|
||||||
if(mami.settings.get('autoEmbedV1')) {
|
|
||||||
const callEmbedOn = eBase.querySelectorAll('a[onclick^="Umi.Parser.SockChatBBcode.Embed"]');
|
|
||||||
for(const embedElem of callEmbedOn)
|
|
||||||
if(embedElem.dataset.embed !== '1')
|
|
||||||
embedElem.click();
|
|
||||||
}
|
|
||||||
|
|
||||||
if(mami.settings.get('autoScroll'))
|
|
||||||
msgsList.scrollTop = msgsList.scrollHeight;
|
|
||||||
|
|
||||||
if(window.CustomEvent)
|
if(window.CustomEvent)
|
||||||
window.dispatchEvent(new CustomEvent('umi:ui:message_add', {
|
window.dispatchEvent(new CustomEvent('umi:ui:message_add', {
|
||||||
|
@ -226,14 +400,18 @@ Umi.UI.Messages = (function() {
|
||||||
message: msg,
|
message: msg,
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
msg.markSeen();
|
||||||
},
|
},
|
||||||
Remove: function(msg) {
|
Remove: function(msg) {
|
||||||
|
forceUserInfo = true;
|
||||||
lastMsgUser = null;
|
lastMsgUser = null;
|
||||||
lastMsgChannel = null;
|
lastMsgChannel = null;
|
||||||
lastWasTiny = null;
|
lastWasTiny = null;
|
||||||
$ri('message-' + msg.getId());
|
$ri(`message-${msg.getId()}`);
|
||||||
},
|
},
|
||||||
RemoveAll: function() {
|
RemoveAll: function() {
|
||||||
|
forceUserInfo = true;
|
||||||
lastMsgUser = null;
|
lastMsgUser = null;
|
||||||
lastMsgChannel = null;
|
lastMsgChannel = null;
|
||||||
lastWasTiny = null;
|
lastWasTiny = null;
|
||||||
|
|
|
@ -209,11 +209,6 @@ Umi.UI.Settings = (function() {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: 'playSoundOnConnect',
|
|
||||||
title: 'Play join sound on connect',
|
|
||||||
type: 'checkbox',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: 'windowsLiveMessenger',
|
name: 'windowsLiveMessenger',
|
||||||
title: 'Windows Live Messenger',
|
title: 'Windows Live Messenger',
|
||||||
|
|
Loading…
Reference in a new issue