Emote compact and infinite scroll emote list

This commit is contained in:
Speng Reb 2026-04-21 17:51:03 +02:00
parent e7111689f1
commit 6281b0ead3
2 changed files with 129 additions and 28 deletions

View file

@ -604,34 +604,51 @@ table td {
border-top-width: 0;
}
.emotelist-table {
margin: auto;
}
.emotelist-table { margin: auto; }
.emote-preview-container { width: 60px; height: 60px; float: left; text-align: center; white-space: nowrap; margin: 3px; }
.emote-preview-hax { display: inline-block; vertical-align: middle; height: 100%; }
.emote-preview { max-width: 56px; max-height: 56px; cursor: pointer; }
.emotelist-paginator-container { text-align: center; }
.emote-preview-container {
width: 100px;
height: 100px;
float: left;
text-align: center;
white-space: nowrap;
margin: 5px;
/* Emote browser panel */
#emote-browser {
display: none;
position: fixed;
z-index: 1060;
width: 340px;
background: #272b30;
border: 1px solid #555;
border-radius: 4px;
box-shadow: 0 4px 14px rgba(0,0,0,.6);
padding: 6px;
}
.emote-preview-hax {
display: inline-block;
vertical-align: middle;
height: 100%;
#emote-browser-search {
width: 100%;
margin-bottom: 6px;
background: #1a1d20;
color: #c8c8c8;
border-color: #555;
}
.emote-preview {
max-width: 100px;
max-height: 100px;
#emote-browser-search:focus { border-color: #888; outline: none; box-shadow: none; }
#emote-browser-grid {
display: flex;
flex-wrap: wrap;
gap: 3px;
max-height: 320px;
overflow-y: auto;
}
.emote-browser-item {
width: 52px;
height: 52px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 3px;
flex-shrink: 0;
}
.emotelist-paginator-container {
text-align: center;
}
.emote-browser-item:hover { background: #3a3f44; }
.emote-browser-item img { max-width: 48px; max-height: 48px; object-fit: contain; }
#leftcontrols .btn {
margin-right: 5px;

View file

@ -947,17 +947,101 @@ applyOpts();
})();
var EMOTELISTMODAL = $("#emotelist");
$("#emotelistbtn").on('click', function () {
EMOTELISTMODAL.modal();
});
EMOTELISTMODAL.on('shown.bs.modal', function () { $('.emotelist-search').trigger('focus') });
EMOTELISTMODAL.find(".emotelist-alphabetical").change(function () {
USEROPTS.emotelist_sort = this.checked;
setOpt("emotelist_sort", USEROPTS.emotelist_sort);
});
EMOTELISTMODAL.find(".emotelist-alphabetical").prop("checked", USEROPTS.emotelist_sort);
/* emote browser panel */
var EMOTE_BROWSER_OFFSET = 0;
var EMOTE_BROWSER_BATCH = 40;
var EMOTE_BROWSER_FILTER = '';
$('body').append(
'<div id="emote-browser">' +
'<input id="emote-browser-search" class="form-control input-sm" type="text" placeholder="Search emotes…">' +
'<div id="emote-browser-grid"></div>' +
'</div>'
);
function emoteBrowserMatches() {
if (!CHANNEL.emotes) return [];
var f = EMOTE_BROWSER_FILTER.toLowerCase();
return f ? CHANNEL.emotes.filter(function(e) { return e.name.toLowerCase().indexOf(f) !== -1; })
: CHANNEL.emotes;
}
function emoteBrowserRenderMore() {
var matches = emoteBrowserMatches();
var end = Math.min(EMOTE_BROWSER_OFFSET + EMOTE_BROWSER_BATCH, matches.length);
var grid = document.getElementById('emote-browser-grid');
for (var i = EMOTE_BROWSER_OFFSET; i < end; i++) {
(function(emote) {
var item = document.createElement('div');
item.className = 'emote-browser-item';
item.title = emote.name;
var img = document.createElement('img');
img.src = emote.image;
item.appendChild(img);
item.addEventListener('click', function() {
var cl = document.getElementById('chatline');
var val = cl.value;
if (val && !val.charAt(val.length - 1).match(/\s/)) val += ' ';
cl.value = val + emote.name;
$("#emote-browser").hide();
cl.focus();
});
grid.appendChild(item);
})(matches[i]);
}
EMOTE_BROWSER_OFFSET = end;
}
function emoteBrowserReset() {
EMOTE_BROWSER_OFFSET = 0;
document.getElementById('emote-browser-grid').innerHTML = '';
emoteBrowserRenderMore();
}
function emoteBrowserPosition() {
var btn = $("#emotelistbtn"), off = btn.offset();
var panel = $("#emote-browser");
var pw = panel.outerWidth(), ph = panel.outerHeight();
var ww = $(window).width(), wh = $(window).height();
var left = off.left;
if (left + pw > ww - 8) left = Math.max(8, off.left + btn.outerWidth() - pw);
var top = off.top - ph - 4;
if (top < 8) top = off.top + btn.outerHeight() + 4;
panel.css({ top: top, left: left });
}
$("#emotelistbtn").on('click', function () {
var panel = $("#emote-browser");
if (panel.is(':visible')) { panel.hide(); return; }
EMOTE_BROWSER_FILTER = '';
$("#emote-browser-search").val('');
emoteBrowserReset();
panel.show();
emoteBrowserPosition();
document.getElementById('emote-browser-search').focus();
});
$(document).on('click.emotebrowser', function (e) {
if (!$(e.target).closest('#emote-browser, #emotelistbtn').length)
$("#emote-browser").hide();
});
$(document).on('input', '#emote-browser-search', function () {
EMOTE_BROWSER_FILTER = this.value;
emoteBrowserReset();
});
document.getElementById('emote-browser-grid').addEventListener('scroll', function () {
if (this.scrollTop + this.clientHeight >= this.scrollHeight - 60)
emoteBrowserRenderMore();
});
$("#fullscreenbtn").on('click', function () {
var elem = document.querySelector("#videowrap .embed-responsive");
// this shit is why frontend web development sucks