Merge pull request #11 from Spengreb/emote-selector-better-modal

Emote selector can be resized
This commit is contained in:
Spengreb 2026-05-21 13:47:29 +02:00 committed by GitHub
commit 8e9bd64e5b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 129 additions and 4 deletions

View file

@ -625,11 +625,18 @@ table td {
position: fixed; position: fixed;
z-index: 1060; z-index: 1060;
width: 340px; width: 340px;
height: 360px;
min-width: 260px;
min-height: 220px;
max-width: 90vw;
max-height: 85vh;
background: #272b30; background: #272b30;
border: 1px solid #555; border: 1px solid #555;
border-radius: 4px; border-radius: 4px;
box-shadow: 0 4px 14px rgba(0,0,0,.6); box-shadow: 0 4px 14px rgba(0,0,0,.6);
padding: 6px; padding: 6px;
--emote-browser-item-size: 52px;
--emote-browser-image-size: 48px;
} }
#emote-browser-search { #emote-browser-search {
width: 100%; width: 100%;
@ -643,12 +650,12 @@ table td {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
gap: 3px; gap: 3px;
max-height: 320px; height: calc(100% - 38px);
overflow-y: auto; overflow-y: auto;
} }
.emote-browser-item { .emote-browser-item {
width: 52px; width: var(--emote-browser-item-size);
height: 52px; height: var(--emote-browser-item-size);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -657,7 +664,29 @@ table td {
flex-shrink: 0; flex-shrink: 0;
} }
.emote-browser-item:hover { background: #3a3f44; } .emote-browser-item:hover { background: #3a3f44; }
.emote-browser-item img { max-width: 48px; max-height: 48px; object-fit: contain; } .emote-browser-item img { max-width: var(--emote-browser-image-size); max-height: var(--emote-browser-image-size); object-fit: contain; }
.emote-browser-resize-handle {
position: absolute;
width: 14px;
height: 14px;
border-radius: 50%;
background: linear-gradient(145deg, rgba(215, 215, 215, 0.65), rgba(150, 150, 150, 0.55));
border: 1px solid rgba(18, 20, 22, 0.55);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
z-index: 2;
opacity: 0.85;
transition: transform 120ms ease, opacity 120ms ease, box-shadow 120ms ease;
}
.emote-browser-resize-handle:hover {
opacity: 1;
transform: scale(1.08);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
}
.emote-browser-resize-handle.ne { top: -7px; right: -7px; cursor: nesw-resize; }
.emote-browser-resize-handle.nw { top: -7px; left: -7px; cursor: nwse-resize; }
.emote-browser-resize-handle.se { bottom: -7px; right: -7px; cursor: nwse-resize; }
.emote-browser-resize-handle.sw { bottom: -7px; left: -7px; cursor: nesw-resize; }
#leftcontrols .btn { #leftcontrols .btn {
margin-right: 5px; margin-right: 5px;

View file

@ -962,9 +962,28 @@ $('body').append(
'<div id="emote-browser">' + '<div id="emote-browser">' +
'<input id="emote-browser-search" class="form-control input-sm" type="text" placeholder="Search emotes…">' + '<input id="emote-browser-search" class="form-control input-sm" type="text" placeholder="Search emotes…">' +
'<div id="emote-browser-grid"></div>' + '<div id="emote-browser-grid"></div>' +
'<div class="emote-browser-resize-handle ne" data-dir="ne"></div>' +
'<div class="emote-browser-resize-handle nw" data-dir="nw"></div>' +
'<div class="emote-browser-resize-handle se" data-dir="se"></div>' +
'<div class="emote-browser-resize-handle sw" data-dir="sw"></div>' +
'</div>' '</div>'
); );
function updateEmoteBrowserScale() {
var panel = document.getElementById('emote-browser');
if (!panel) return;
var panelWidth = panel.clientWidth;
var panelHeight = panel.clientHeight;
var itemByWidth = Math.floor((panelWidth - 48) / 6);
var itemByHeight = Math.floor((panelHeight - 90) / 4);
var itemSize = Math.max(40, Math.min(88, itemByWidth, itemByHeight));
var imageSize = Math.max(36, itemSize - 4);
panel.style.setProperty('--emote-browser-item-size', itemSize + 'px');
panel.style.setProperty('--emote-browser-image-size', imageSize + 'px');
}
function emoteBrowserMatches() { function emoteBrowserMatches() {
if (!CHANNEL.emotes) return []; if (!CHANNEL.emotes) return [];
var f = EMOTE_BROWSER_FILTER.toLowerCase(); var f = EMOTE_BROWSER_FILTER.toLowerCase();
@ -1016,6 +1035,74 @@ function emoteBrowserPosition() {
panel.css({ top: top, left: left }); panel.css({ top: top, left: left });
} }
function clampEmoteBrowserToViewport() {
var panel = document.getElementById('emote-browser');
if (!panel) return;
var rect = panel.getBoundingClientRect();
var maxLeft = window.innerWidth - rect.width - 8;
var maxTop = window.innerHeight - rect.height - 8;
var left = Math.min(Math.max(rect.left, 8), Math.max(8, maxLeft));
var top = Math.min(Math.max(rect.top, 8), Math.max(8, maxTop));
panel.style.left = left + 'px';
panel.style.top = top + 'px';
}
$(document).on('mousedown', '#emote-browser .emote-browser-resize-handle', function (ev) {
ev.preventDefault();
ev.stopPropagation();
var panel = document.getElementById('emote-browser');
var dir = ev.target.getAttribute('data-dir');
if (!panel || !dir) return;
var startX = ev.clientX;
var startY = ev.clientY;
var startRect = panel.getBoundingClientRect();
var minW = 260, minH = 220;
var maxW = Math.floor(window.innerWidth * 0.9);
var maxH = Math.floor(window.innerHeight * 0.85);
function onMove(moveEv) {
var dx = moveEv.clientX - startX;
var dy = moveEv.clientY - startY;
var left = startRect.left;
var top = startRect.top;
var width = startRect.width;
var height = startRect.height;
if (dir.indexOf('e') !== -1) {
width = Math.max(minW, Math.min(maxW, startRect.width + dx));
}
if (dir.indexOf('s') !== -1) {
height = Math.max(minH, Math.min(maxH, startRect.height + dy));
}
if (dir.indexOf('w') !== -1) {
width = Math.max(minW, Math.min(maxW, startRect.width - dx));
left = startRect.right - width;
}
if (dir.indexOf('n') !== -1) {
height = Math.max(minH, Math.min(maxH, startRect.height - dy));
top = startRect.bottom - height;
}
panel.style.left = Math.max(8, left) + 'px';
panel.style.top = Math.max(8, top) + 'px';
panel.style.width = width + 'px';
panel.style.height = height + 'px';
updateEmoteBrowserScale();
clampEmoteBrowserToViewport();
}
function onUp() {
document.removeEventListener('mousemove', onMove);
document.removeEventListener('mouseup', onUp);
}
document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onUp);
});
$("#emotelistbtn").on('click', function () { $("#emotelistbtn").on('click', function () {
var panel = $("#emote-browser"); var panel = $("#emote-browser");
if (panel.is(':visible')) { panel.hide(); return; } if (panel.is(':visible')) { panel.hide(); return; }
@ -1023,7 +1110,9 @@ $("#emotelistbtn").on('click', function () {
$("#emote-browser-search").val(''); $("#emote-browser-search").val('');
emoteBrowserReset(); emoteBrowserReset();
panel.show(); panel.show();
updateEmoteBrowserScale();
emoteBrowserPosition(); emoteBrowserPosition();
clampEmoteBrowserToViewport();
document.getElementById('emote-browser-search').focus(); document.getElementById('emote-browser-search').focus();
}); });
@ -1042,6 +1131,13 @@ document.getElementById('emote-browser-grid').addEventListener('scroll', functio
emoteBrowserRenderMore(); emoteBrowserRenderMore();
}); });
$(window).on('resize', function () {
updateEmoteBrowserScale();
if ($("#emote-browser").is(':visible')) {
clampEmoteBrowserToViewport();
}
});
$("#fullscreenbtn").on('click', function () { $("#fullscreenbtn").on('click', function () {
var elem = document.querySelector("#videowrap .embed-responsive"); var elem = document.querySelector("#videowrap .embed-responsive");
// this shit is why frontend web development sucks // this shit is why frontend web development sucks