@@ -1,208 +0,0 @@ | |||
define([ | |||
'html!ui/templates/messages/tplTab' | |||
], function ( | |||
tplTab | |||
) { | |||
const extensionObj = { | |||
processChat: function (msgConfig) { | |||
const { message, event: keyboardEvent } = msgConfig; | |||
const { key } = keyboardEvent; | |||
const { el, currentChannel } = this; | |||
const optionContainer = this.find('.channelOptions'); | |||
if (message.length) { | |||
if (el.hasClass('picking')) | |||
msgConfig.cancel = true; | |||
return; | |||
} | |||
if (key === 'Enter') { | |||
const selectedSubPick = optionContainer.find('.option.selected'); | |||
if (selectedSubPick.length) { | |||
this.onPickSubChannel(selectedSubPick.html(), currentChannel); | |||
return; | |||
} | |||
} | |||
//If we're busy picking a sub channel, we can use keyboard nav | |||
const isPicking = el.hasClass('picking'); | |||
const currentSelection = optionContainer.find('.option.selected'); | |||
if (isPicking && currentSelection.length) { | |||
const delta = { | |||
ArrowUp: -1, | |||
ArrowDown: 1 | |||
}[key]; | |||
if (delta) { | |||
const options = optionContainer.find('.option'); | |||
const currentIndex = currentSelection.eq(0).index(); | |||
let nextIndex = (currentIndex + delta) % options.length; | |||
currentSelection.removeClass('selected'); | |||
options.eq(nextIndex).addClass('selected'); | |||
} | |||
} | |||
const pick = { | |||
'%': 'party', | |||
'!': 'global', | |||
$: 'custom', | |||
'@': 'direct' | |||
}[key]; | |||
if (!pick) { | |||
if (isPicking) | |||
msgConfig.cancel = true; | |||
return; | |||
} | |||
if (currentChannel === pick) { | |||
if (pick === 'direct') | |||
this.lastPrivateChannel = null; | |||
else if (pick === 'custom') | |||
this.lastCustomChannel = null; | |||
} | |||
this.onPickChannel(pick, true); | |||
msgConfig.cancel = true; | |||
}, | |||
onPickChannel: function (channel, autoPickSub) { | |||
this.currentChannel = channel; | |||
this.currentSubChannel = null; | |||
const showSubChannels = ( | |||
['direct', 'custom'].includes(channel) && | |||
( | |||
!autoPickSub || | |||
( | |||
channel === 'direct' && | |||
!this.lastPrivateChannel | |||
) || | |||
( | |||
channel === 'custom' && | |||
!this.lastCustomChannel | |||
) | |||
) | |||
); | |||
if (!showSubChannels) { | |||
this.find('.channelOptions').removeClass('active'); | |||
let showValue = { | |||
direct: this.lastPrivateChannel, | |||
custom: this.lastCustomChannel | |||
}[channel]; | |||
if (channel === 'direct' || channel === 'custom') | |||
this.currentSubChannel = showValue; | |||
showValue = showValue || channel; | |||
this.find('.channelPicker').html(showValue); | |||
this.find('input').focus(); | |||
this.el.removeClass('picking'); | |||
} else | |||
this.onShowChannelOptions(channel); | |||
}, | |||
onPickSubChannel: function (subChannel, channel) { | |||
this.currentSubChannel = subChannel; | |||
this.find('.channelOptions').removeClass('active'); | |||
this.find('.channelPicker').html(subChannel); | |||
const elInput = this.find('input'); | |||
elInput.focus(); | |||
if (channel === 'custom') { | |||
if (subChannel === 'join new') { | |||
elInput.val('/join channelName'); | |||
elInput[0].setSelectionRange(6, 17); | |||
} else if (subChannel === 'leave') { | |||
elInput.val('/leave channelName'); | |||
elInput[0].setSelectionRange(7, 18); | |||
} | |||
} | |||
this.el.removeClass('picking'); | |||
}, | |||
onShowChannelOptions: function (currentPick) { | |||
const optionContainer = this.find('.channelOptions') | |||
.addClass('active') | |||
.empty(); | |||
const options = []; | |||
let handlerOnClick = this.onPickChannel; | |||
this.el.addClass('picking'); | |||
if (!currentPick) { | |||
options.push('global', 'custom'); | |||
if (this.privateChannels.length) | |||
options.push('direct'); | |||
//Hack...surely we can find a more sane way to do this | |||
if ($('.uiParty .member').length) | |||
options.push('party'); | |||
} else { | |||
handlerOnClick = this.onPickSubChannel; | |||
if (currentPick === 'direct') | |||
options.push(...this.privateChannels); | |||
else if (currentPick === 'custom') | |||
options.push(...this.customChannels, 'join new', 'leave'); | |||
} | |||
if (!options.length) { | |||
this.onPickChannel('global'); | |||
return; | |||
} | |||
let addSelectStyleTo = null; | |||
if (currentPick) | |||
addSelectStyleTo = this.currentSubChannel || options[0]; | |||
options.forEach(o => { | |||
const shortcut = { | |||
global: ' (!)', | |||
direct: ' (@)', | |||
party: ' (%)', | |||
custom: ' ($)' | |||
}[o] || ''; | |||
const html = `<div class='option' shortcut='${shortcut}'>${o}</div>`; | |||
const el = $(html) | |||
.appendTo(optionContainer) | |||
.on('click', handlerOnClick.bind(this, o, currentPick)) | |||
.on('hover', this.stopKeyboardNavForOptions.bind(this)); | |||
if (o === addSelectStyleTo) | |||
el.addClass('selected'); | |||
}); | |||
}, | |||
stopKeyboardNavForOptions: function () { | |||
this.find('.channelOptions .option.selected').removeClass('selected'); | |||
} | |||
}; | |||
return { | |||
init: function () { | |||
$.extend(this, extensionObj); | |||
//This whole hoverFilter business is a filthy hack | |||
this.find('.channelPicker, .channelOptions, .filter:not(.channel)') | |||
.on('mouseover', this.onFilterHover.bind(this, true)) | |||
.on('mouseleave', this.onFilterHover.bind(this, false)); | |||
this.find('.channelPicker').on('click', this.onShowChannelOptions.bind(this, null)); | |||
} | |||
}; | |||
}); |
@@ -1,382 +0,0 @@ | |||
define([ | |||
'js/system/events', | |||
'html!ui/templates/messages/template', | |||
'html!ui/templates/messages/tplTab', | |||
'css!ui/templates/messages/styles', | |||
'ui/templates/messages/mobile', | |||
'ui/templates/messages/channelPicker', | |||
'js/input', | |||
'js/system/client', | |||
'js/config' | |||
], function ( | |||
events, | |||
template, | |||
tplTab, | |||
styles, | |||
messagesMobile, | |||
channelPicker, | |||
input, | |||
client, | |||
config | |||
) { | |||
return { | |||
tpl: template, | |||
maxChatLength: 255, | |||
hoverItem: null, | |||
hoverFilter: false, | |||
currentChannel: 'global', | |||
currentSubChannel: null, | |||
privateChannels: [], | |||
lastPrivateChannel: null, | |||
customChannels: [], | |||
lastCustomChannel: null, | |||
postRender: function () { | |||
[ | |||
'onGetMessages', | |||
'onDoWhisper', | |||
'onJoinChannel', | |||
'onLeaveChannel', | |||
'onClickFilter', | |||
'onGetCustomChatChannels', | |||
'onKeyDown', | |||
'onKeyUp' | |||
].forEach(e => this.onEvent(e, this[e].bind(this))); | |||
this.find('.filter:not(.channel)').on('click', this.onClickFilter.bind(this)); | |||
channelPicker.init.call(this); | |||
if (isMobile) | |||
messagesMobile.init.call(this); | |||
else { | |||
this.find('input') | |||
.on('keydown', this.sendChat.bind(this)) | |||
.on('input', this.enforceMaxMsgLength.bind(this)) | |||
.on('blur', this.toggle.bind(this, false, true)); | |||
} | |||
}, | |||
update: function () { | |||
if (isMobile) | |||
return; | |||
if (this.el.hasClass('typing')) | |||
return; | |||
const time = new Date(); | |||
const hours = time.getUTCHours().toString().padStart(2, 0); | |||
const minutes = time.getUTCMinutes().toString().padStart(2, 0); | |||
let elTime = this.find('.time'); | |||
const timeString = `[ ${hours}:${minutes} ]`; | |||
if (elTime.html() !== timeString) | |||
elTime.html(timeString); | |||
}, | |||
enforceMaxMsgLength: function () { | |||
let textbox = this.find('input'); | |||
let val = textbox.val(); | |||
if (val.length <= this.maxChatLength) | |||
return; | |||
val = val.substr(0, this.maxChatLength); | |||
textbox.val(val); | |||
}, | |||
onGetCustomChatChannels: function (channels) { | |||
channels.forEach(c => this.onJoinChannel(c)); | |||
}, | |||
onJoinChannel: function (channel) { | |||
const container = this.find('.filters'); | |||
const channelName = channel.trim(); | |||
this.customChannels.spliceWhere(c => c === channel); | |||
this.find(`[filter="${channelName}"]`).remove(); | |||
this.customChannels.push(channel); | |||
$(tplTab) | |||
.appendTo(container) | |||
.addClass('channel') | |||
.attr('filter', channelName) | |||
.html(channelName) | |||
.on('mouseover', this.onFilterHover.bind(this, true)) | |||
.on('mouseleave', this.onFilterHover.bind(this, false)) | |||
.on('click', this.onClickFilter.bind(this)); | |||
}, | |||
onLeaveChannel: function (channel) { | |||
this.customChannels.spliceWhere(c => c === channel); | |||
this.find(`.filters div[filter="${channel}"]`).remove(); | |||
}, | |||
onFilterHover: function (hover) { | |||
this.hoverFilter = hover; | |||
}, | |||
onClickFilter: function (e) { | |||
let el = $(e.target); | |||
el.toggleClass('active'); | |||
let filter = el.attr('filter'); | |||
let method = (el.hasClass('active') ? 'show' : 'hide'); | |||
if (method === 'show') | |||
this.find('.list').addClass(filter); | |||
else | |||
this.find('.list').removeClass(filter); | |||
if (el.hasClass('channel')) | |||
this.find('.list .' + filter)[method](); | |||
}, | |||
onKeyDown: function (key) { | |||
if (key === 'enter') | |||
this.toggle(true); | |||
else if (key === 'shift') | |||
this.showItemTooltip(); | |||
else if (key === 'esc' && this.el.hasClass('typing')) | |||
this.toggle(false); | |||
}, | |||
onKeyUp: function (key) { | |||
if (key === 'shift') | |||
this.showItemTooltip(); | |||
}, | |||
onDoWhisper: function (charName) { | |||
this.toggle(true); | |||
this.currentChannel = 'direct'; | |||
this.currentSubChannel = charName; | |||
this.find('.channelPicker').html(charName); | |||
const elInput = this.find('input') | |||
.val('message') | |||
.focus(); | |||
elInput[0].setSelectionRange(0, 7); | |||
}, | |||
//Remember private and custom channels used | |||
trackHistory: function (msg) { | |||
const { subType, source, target, channel } = msg; | |||
if (subType === 'privateIn' || subType === 'privateOut') { | |||
const list = this.privateChannels; | |||
list.spliceWhere(l => l === source || l === target); | |||
//Newest sources are always at the end | |||
list.push(source || target); | |||
if (list.length > 5) | |||
list.splice(0, list.length - 5); | |||
if (subType === 'privateOut' && config.rememberChatChannel) | |||
this.lastPrivateChannel = target; | |||
} else if (subType === 'custom' && config.rememberChatChannel) | |||
this.lastCustomChannel = channel; | |||
}, | |||
onGetMessages: function (e) { | |||
let messages = e.messages; | |||
if (!messages.length) | |||
messages = [messages]; | |||
let container = this.find('.list'); | |||
const [ { scrollHeight, clientHeight, scrollTop } ] = container; | |||
const isAtMaxScroll = scrollTop >= (scrollHeight - clientHeight); | |||
messages.forEach(m => { | |||
this.trackHistory(m); | |||
let message = m.message; | |||
if (m.source) { | |||
if (window.player.social.isPlayerBlocked(m.source)) | |||
return; | |||
} | |||
if (m.item) { | |||
let source = message.split(':')[0]; | |||
message = source + ': <span class="q' + (m.item.quality || 0) + '">' + message.replace(source + ': ', '') + '</span>'; | |||
} | |||
let el = $('<div class="list-message ' + m.class + '">' + message + '</div>') | |||
.appendTo(container); | |||
if (m.has('type')) | |||
el.addClass(m.type); | |||
else | |||
el.addClass('info'); | |||
if (m.has('channel')) | |||
el.addClass(m.channel); | |||
if (m.item) { | |||
let clickHander = () => {}; | |||
let moveHandler = this.showItemTooltip.bind(this, el, m.item); | |||
if (isMobile) | |||
[clickHander, moveHandler] = [moveHandler, clickHander]; | |||
el.find('span') | |||
.on('mousemove', moveHandler) | |||
.on('mousedown', clickHander) | |||
.on('mouseleave', this.hideItemTooltip.bind(this)); | |||
} | |||
if (m.type) { | |||
let isChannel = (['info', 'chat', 'loot', 'rep'].indexOf(m.type) === -1); | |||
if (isChannel) { | |||
if (this.find('.filter[filter="' + m.type + '"]').hasClass('active')) | |||
el.show(); | |||
} | |||
if (isMobile && ['loot', 'info'].indexOf(m.type) !== -1) { | |||
events.emit('onGetAnnouncement', { | |||
msg: m.message | |||
}); | |||
} | |||
} | |||
}); | |||
if (!this.el.hasClass('typing') || isAtMaxScroll) | |||
container.scrollTop(9999999); | |||
}, | |||
hideItemTooltip: function () { | |||
if (this.dragEl) { | |||
this.hoverCell = null; | |||
return; | |||
} | |||
events.emit('onHideItemTooltip', this.hoverItem); | |||
this.hoverItem = null; | |||
}, | |||
showItemTooltip: function (el, item, e) { | |||
if (item) | |||
this.hoverItem = item; | |||
else | |||
item = this.hoverItem; | |||
if (!item) | |||
return; | |||
let ttPos = null; | |||
if (el) { | |||
ttPos = { | |||
x: ~~(e.clientX + 32), | |||
y: ~~(e.clientY) | |||
}; | |||
} | |||
let bottomAlign = !isMobile; | |||
events.emit('onShowItemTooltip', item, ttPos, true, bottomAlign); | |||
}, | |||
toggle: function (show, isFake, e) { | |||
if (isFake && this.hoverFilter) | |||
return; | |||
input.resetKeys(); | |||
this.el.removeClass('typing'); | |||
let textbox = this.find('input'); | |||
if (show) { | |||
this.el.addClass('typing'); | |||
if (!config.rememberChatChannel) { | |||
this.currentChannel = 'global'; | |||
this.currentSubChannel = null; | |||
} | |||
this.find('.channelPicker').html(this.currentSubChannel || this.currentChannel); | |||
textbox.focus(); | |||
this.find('.list').scrollTop(9999999); | |||
} else { | |||
this.find('.channelOptions').removeClass('active'); | |||
textbox.val(''); | |||
this.el.removeClass('picking'); | |||
if (['direct', 'custom'].includes(this.currentChannel) && (!this.currentSubChannel || ['join new', 'leave'].includes(this.currentSubChannel))) { | |||
this.currentSubChannel = null; | |||
this.currentChannel = 'global'; | |||
} | |||
} | |||
if (e) | |||
e.stopPropagation(); | |||
}, | |||
sendChat: function (e) { | |||
let textbox = this.find('input'); | |||
let msgConfig = { | |||
success: true, | |||
message: textbox.val(), | |||
event: e, | |||
cancel: false | |||
}; | |||
this.processChat(msgConfig); | |||
if (msgConfig.cancel || this.el.hasClass('picking')) | |||
return false; | |||
const { which: charCode } = e; | |||
if ([9, 27].includes(charCode) || charCode !== 13) { | |||
if (charCode === 9) { | |||
e.preventDefault(); | |||
textbox.val(`${textbox.val()} `); | |||
} else if (charCode === 27) | |||
this.toggle(false); | |||
return; | |||
} | |||
events.emit('onBeforeChat', msgConfig); | |||
let val = msgConfig.message | |||
.split('<').join('<') | |||
.split('>').join('>'); | |||
if (!msgConfig.success) { | |||
this.toggle(false); | |||
return; | |||
} | |||
if (val.trim() === '') { | |||
this.toggle(false); | |||
return; | |||
} | |||
client.request({ | |||
cpn: 'social', | |||
method: 'chat', | |||
data: { | |||
message: val, | |||
type: this.currentChannel, | |||
subType: this.currentSubChannel | |||
} | |||
}); | |||
this.toggle(); | |||
} | |||
}; | |||
}); |
@@ -1,123 +0,0 @@ | |||
define([ | |||
'html!ui/templates/messages/tplTab' | |||
], function ( | |||
tplTab | |||
) { | |||
const extensionObj = { | |||
renderKeyboard: function () { | |||
this.find('.keyboard').remove(); | |||
let container = $('<div class="keyboard"></div>') | |||
.appendTo(this.el); | |||
let keyboard = { | |||
0: 'qwertyuiop|asdfghjkl|zxcvbnm', | |||
1: 'QWERTYUIOP|ASDFGHJKL|ZXCVBNM', | |||
2: '1234567890|@#&*-+=()|_$"\';/' | |||
}[this.kbUpper].split(''); | |||
//Hacky: Insert control characters in correct positions | |||
//Backspace goes after 'm' | |||
if (this.kbUpper === 0) { | |||
keyboard.splice(keyboard.indexOf('z'), 0, 'caps'); | |||
keyboard.splice(keyboard.indexOf('m') + 1, 0, '<<'); | |||
} else if (this.kbUpper === 1) { | |||
keyboard.splice(keyboard.indexOf('Z'), 0, 'caps'); | |||
keyboard.splice(keyboard.indexOf('M') + 1, 0, '<<'); | |||
} else if (this.kbUpper === 2) | |||
keyboard.splice(keyboard.indexOf('/') + 1, 0, '<<'); | |||
keyboard.push(...['|', '123', ',', 'space', '.', 'send']); | |||
let row = 0; | |||
keyboard.forEach(k => { | |||
if (k === '|') { | |||
row++; | |||
const postGapCount = row === 4 ? 0 : row - 1; | |||
for (let i = 0; i < postGapCount; i++) | |||
$('<div class="gap" />').appendTo(container); | |||
$('<div class="newline" />').appendTo(container); | |||
const preGapCount = row === 3 ? 0 : row; | |||
for (let i = 0; i < preGapCount; i++) | |||
$('<div class="gap" />').appendTo(container); | |||
return; | |||
} | |||
let className = (k.length === 1) ? 'key' : 'key special'; | |||
if (k === ' ') { | |||
k = '.'; | |||
className = 'key hidden'; | |||
} | |||
className += ' ' + k; | |||
let elKey = $(`<div class="${className}">${k}</div>`) | |||
.appendTo(container); | |||
if (!className.includes('hidden')) | |||
elKey.on('click', this.clickKey.bind(this, k)); | |||
}); | |||
}, | |||
clickKey: function (key) { | |||
window.navigator.vibrate(20); | |||
let elInput = this.find('input'); | |||
const handler = { | |||
caps: () => { | |||
this.kbUpper = (this.kbUpper + 1) % 2; | |||
this.renderKeyboard(); | |||
}, | |||
123: () => { | |||
this.kbUpper = (this.kbUpper === 2) ? 0 : 2; | |||
this.renderKeyboard(); | |||
}, | |||
space: () => this.clickKey(' '), | |||
'<<': () => { | |||
elInput.val(elInput.val().slice(0, -1)); | |||
this.find('.input').html(elInput.val()); | |||
}, | |||
send: () => { | |||
this.sendChat({ which: 13 }); | |||
this.find('.input').html(''); | |||
this.find('input').val(''); | |||
} | |||
}[key]; | |||
if (handler) { | |||
handler(); | |||
return; | |||
} | |||
elInput.val(elInput.val() + key); | |||
this.enforceMaxMsgLength(); | |||
this.find('.input').html(elInput.val()); | |||
} | |||
}; | |||
return { | |||
init: function () { | |||
$.extend(this, extensionObj); | |||
this.kbUpper = 0; | |||
this.el.on('click', this.toggle.bind(this, true)); | |||
this.renderKeyboard(); | |||
$(tplTab) | |||
.appendTo(this.find('.filters')) | |||
.addClass('btnClose') | |||
.html('x') | |||
.on('click', this.toggle.bind(this, false, true)); | |||
} | |||
}; | |||
}); |
@@ -1,420 +0,0 @@ | |||
@import "../../../css/colors.less"; | |||
@pad: 8px; | |||
@btnSize: 64px; | |||
.uiMessages { | |||
position: absolute; | |||
left: 10px; | |||
bottom: 10px; | |||
width: 480px; | |||
pointer-events: none; | |||
display: flex; | |||
flex-direction: column; | |||
.filters { | |||
display: none; | |||
width: 100%; | |||
flex-wrap: wrap; | |||
.filter { | |||
height: 100%; | |||
background-color: @blackC; | |||
float: left; | |||
color: @blackA; | |||
margin-right: 10px; | |||
margin-bottom: 10px; | |||
padding: 5px 10px; | |||
cursor: pointer; | |||
&:hover { | |||
background-color: @blackB; | |||
color: @grayD; | |||
} | |||
&.active { | |||
background-color: @blackB; | |||
color: @blueB; | |||
&:hover { | |||
background-color: @blackA; | |||
color: @grayB; | |||
} | |||
} | |||
} | |||
} | |||
.list { | |||
overflow-y: hidden; | |||
width: 100%; | |||
max-height: 320px; | |||
.list-message { | |||
display: none; | |||
width: 100%; | |||
padding: 5px 10px; | |||
color: white; | |||
filter: drop-shadow(0px -2px 0px @blackD) | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
-moz-filter: drop-shadow(0px -2px 0px @blackD) | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
word-wrap: break-word; | |||
line-height: 18px; | |||
&.q { | |||
color: @grayB; | |||
} | |||
&.q0 { | |||
color: @white; | |||
} | |||
&.q1 { | |||
color: @greenB; | |||
} | |||
a, | |||
&.q2 { | |||
color: @blueB; | |||
} | |||
&.q3 { | |||
color: @purpleA; | |||
} | |||
&.q4 { | |||
color: @orangeA; | |||
} | |||
&.color-green { | |||
color: @green; | |||
} | |||
&.color-red { | |||
color: @red; | |||
} | |||
&.color-cyan { | |||
color: @blueA; | |||
} | |||
&.color-tealC { | |||
color: @tealC; | |||
} | |||
} | |||
&.rep .rep { | |||
display: block; | |||
} | |||
&.chat .chat { | |||
display: block; | |||
} | |||
&.info .info { | |||
display: block; | |||
} | |||
&.loot .loot { | |||
display: block; | |||
} | |||
} | |||
.bottom { | |||
display: none; | |||
.channelPicker { | |||
min-width: 100px; | |||
color: 1; | |||
display: flex; | |||
justify-content: center; | |||
align-items: center; | |||
color: @white; | |||
background-color: @blueC; | |||
cursor: pointer; | |||
padding: 0px 10px; | |||
&:after { | |||
content: '▾'; | |||
margin-left: 10px; | |||
} | |||
&:hover { | |||
background-color: @blueD; | |||
} | |||
} | |||
.el { | |||
flex: 1; | |||
width: 100%; | |||
color: @white; | |||
&.textbox.message { | |||
display: none; | |||
background-color: @gray; | |||
text-align: left; | |||
padding: 5px 10px; | |||
} | |||
} | |||
&.time { | |||
display: flex; | |||
align-items: center; | |||
padding-left: 10px; | |||
background-color: transparent; | |||
height: 35px; | |||
color: @white; | |||
text-align: left; | |||
filter: drop-shadow(0px -2px 0px @blackD) | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
-moz-filter: drop-shadow(0px -2px 0px @blackD) | |||
drop-shadow(0px 2px 0px @blackD) | |||
drop-shadow(2px 0px 0px @blackD) | |||
drop-shadow(-2px 0px 0px @blackD); | |||
} | |||
&.channelOptions { | |||
display: none; | |||
flex-direction: column; | |||
position: absolute; | |||
left: 0px; | |||
bottom: 0px; | |||
min-width: 100px; | |||
.option { | |||
height: 35px; | |||
display: flex; | |||
justify-content: center; | |||
align-items: center; | |||
color: @grayB; | |||
background-color: @blackA; | |||
cursor: pointer; | |||
padding: 0px 10px; | |||
&:after { | |||
content: attr(shortcut); | |||
margin-left: 10px; | |||
color: @grayC; | |||
} | |||
&:hover, | |||
&.selected { | |||
background-color: @grayD; | |||
color: @white; | |||
} | |||
} | |||
} | |||
} | |||
&.typing { | |||
box-shadow: 0 -2px 0 @black, 0 2px 0 @black, 2px 0 0 @black, -2px 0 0 @black; | |||
pointer-events: all; | |||
.filters { | |||
pointer-events: all; | |||
display: flex; | |||
} | |||
.list { | |||
overflow-y: auto; | |||
background-color: @darkGray; | |||
.list-message { | |||
filter: none; | |||
} | |||
} | |||
.bottom { | |||
display: flex; | |||
.el.textbox { | |||
&.message:not(.input) { | |||
display: block; | |||
} | |||
} | |||
} | |||
.time { | |||
display: none; | |||
} | |||
.channelOptions { | |||
display: none; | |||
&.active { | |||
display: flex; | |||
} | |||
} | |||
} | |||
&.active { | |||
.list-message { | |||
opacity: 1 !important; | |||
} | |||
} | |||
&.picking { | |||
&:before { | |||
position: absolute; | |||
content: ''; | |||
left: 0px; | |||
top: 0px; | |||
width: 100%; | |||
height: 100%; | |||
background-color: @blackD; | |||
opacity: 0.7; | |||
} | |||
} | |||
} | |||
.mobile .uiMessages { | |||
padding: 0px; | |||
pointer-events: all; | |||
.btnClose.active { | |||
float: right; | |||
margin-right: 0px; | |||
padding: 5px 20px; | |||
color: @redA; | |||
} | |||
input { | |||
display: none; | |||
} | |||
.filters { | |||
margin-bottom: 0px; | |||
flex-shrink: 0; | |||
background-color: @darkGray; | |||
} | |||
.list { | |||
height: 100%; | |||
max-height: 100%; | |||
} | |||
&.typing { | |||
left: 0px; | |||
top: 0px; | |||
width: 100%; | |||
height: 100%; | |||
background-color: fade(@darkGray, 90%); | |||
display: flex; | |||
flex-direction: column; | |||
z-index: 999999998; | |||
.channelPicker { | |||
display: none; | |||
} | |||
.channelOptions { | |||
z-index: 999999999; | |||
} | |||
.bottom { | |||
.input { | |||
display: block; | |||
height: 26px; | |||
flex-shrink: 0; | |||
} | |||
} | |||
.el.textbox.message:not(.input),.time { | |||
display: none; | |||
} | |||
.keyboard { | |||
display: flex; | |||
flex-direction: row; | |||
flex-wrap: wrap; | |||
background-color: @blackC; | |||
justify-content: center; | |||
align-items: center; | |||
height: 140px; | |||
flex-shrink: 0; | |||
.key { | |||
flex: 1; | |||
background-color: @blackA; | |||
color: @white; | |||
padding: 8px 10px; | |||
text-align: center; | |||
&.special { | |||
color: @orangeA; | |||
} | |||
&.hidden { | |||
color: @blackC; | |||
} | |||
&.space { | |||
flex: 5; | |||
} | |||
} | |||
.newline { | |||
width: 100%; | |||
} | |||
.gap { | |||
width: 5%; | |||
flex-shrink: 0; | |||
} | |||
} | |||
} | |||
&:not(.typing) { | |||
top: 10px; | |||
right: 84px; | |||
left: auto; | |||
bottom: auto; | |||
width: @btnSize; | |||
height: @btnSize; | |||
background-color: fade(@darkGray, 90%); | |||
&:after { | |||
content: ''; | |||
position: absolute; | |||
left: 0px; | |||
top: 0px; | |||
background: url('../../../images/uiIcons.png'); | |||
background-position: -0px -128px; | |||
width: @btnSize; | |||
height: @btnSize; | |||
} | |||
> * { | |||
display: none; | |||
} | |||
} | |||
} |
@@ -1,20 +0,0 @@ | |||
<div class="uiMessages active"> | |||
<div class="filters"> | |||
<div class="btn filter active" filter="info">info</div> | |||
<div class="btn filter active" filter="rep">reputation</div> | |||
<div class="btn filter active" filter="chat">players</div> | |||
<div class="btn filter active" filter="loot">loot</div> | |||
</div> | |||
<div class="list rep chat info loot"></div> | |||
<div class="bottom"> | |||
<div class="channelPicker"></div> | |||
<input type="text" class="el textbox message"> | |||
<div class="input el textbox message"></div> | |||
</div> | |||
<div class="bottom time"></div> | |||
<div class="bottom channelOptions"> | |||
<div class="option">global</div> | |||
<div class="option">party</div> | |||
<div class="option">direct</div> | |||
</div> | |||
</div> |
@@ -1 +0,0 @@ | |||
<div class="filter active" filter="filterName"></div> |
@@ -11,19 +11,19 @@ const sendRegularMessage = ({ obj }, messageInfo) => { | |||
const msgClass = item ? `q${item.quality}` : 'color-grayB'; | |||
const msgData = { | |||
type: 'chat', | |||
source, | |||
prefix, | |||
prefixClass, | |||
msg, | |||
msgClass, | |||
item | |||
}; | |||
cons.emit('event', { | |||
event: 'onGetMessages', | |||
data: { | |||
messages: [{ | |||
type: 'chat', | |||
source, | |||
prefix, | |||
prefixClass, | |||
msg, | |||
msgClass, | |||
item | |||
}] | |||
} | |||
data: { messages: [msgData] } | |||
}); | |||
}; | |||
@@ -8,7 +8,7 @@ module.exports = { | |||
// sqlite | |||
// rethink | |||
//eslint-disable-next-line no-process-env | |||
db: process.env.IWD_DB || 'rethink', | |||
db: process.env.IWD_DB || 'sqlite', | |||
//eslint-disable-next-line no-process-env | |||
dbHost: process.env.IWD_DB_HOST || 'localhost', | |||
//eslint-disable-next-line no-process-env | |||
@@ -49,7 +49,7 @@ module.exports = { | |||
if (mod.disabled) | |||
return; | |||
const isMapThread = !!process.send; | |||
const isMapThread = global.instancer; | |||
mod.isMapThread = isMapThread; | |||
mod.events = events; | |||