heystreamer/views/layout_editor.ejs
Bashy 6c7facadce
Some checks failed
CI / check (push) Has been cancelled
rework
2026-04-26 23:00:55 +03:00

91 lines
4.1 KiB
Text
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<h2>Layout editor</h2>
<p><small>Drag the handles in the preview to reposition widgets. Use the form below to adjust style.</small></p>
<div style="position:relative; width:100%; padding-bottom:56.25%; border:1px solid #333; border-radius:8px; overflow:hidden; margin-bottom:1.5rem;">
<iframe
id="preview"
src="/overlay/<%= settings.overlay_id %>/preview"
style="position:absolute; top:0; left:0; width:1920px; height:1080px; border:none; transform-origin:top left;"
scrolling="no"
></iframe>
</div>
<form method="POST" action="/layout">
<h3>Chat style</h3>
<div style="display:grid; grid-template-columns:repeat(3,1fr); gap:1rem;">
<label>Font size (px) <input type="number" name="chat_font_size" value="<%= layout.chat_font_size %>" min="8" max="64"></label>
<label>Font family <input type="text" name="chat_font_family" value="<%= layout.chat_font_family %>"></label>
<label>Text colour <input type="color" name="chat_text_color" value="<%= layout.chat_text_color %>"></label>
<label>Background opacity (01) <input type="number" name="chat_bg_opacity" value="<%= layout.chat_bg_opacity %>" min="0" max="1" step="0.05"></label>
<label>Border radius (px) <input type="number" name="chat_border_radius" value="<%= layout.chat_border_radius %>" min="0" max="32"></label>
</div>
<h3>Alert style</h3>
<div style="display:grid; grid-template-columns:repeat(3,1fr); gap:1rem;">
<label>Font size (px) <input type="number" name="alert_font_size" value="<%= layout.alert_font_size %>" min="12" max="96"></label>
<label>Text colour <input type="color" name="alert_text_color" value="<%= layout.alert_text_color %>"></label>
<label>Background opacity (01) <input type="number" name="alert_bg_opacity" value="<%= layout.alert_bg_opacity %>" min="0" max="1" step="0.05"></label>
</div>
<button type="submit">Save style</button>
</form>
<script src="https://cdn.jsdelivr.net/npm/interact.js@1.10.27/dist/interact.min.js"></script>
<script>
const iframe = document.getElementById('preview');
function applyScale() {
const scale = iframe.parentElement.offsetWidth / 1920;
iframe.style.transform = `scale(${scale})`;
}
applyScale();
window.addEventListener('resize', applyScale);
iframe.addEventListener('load', () => {
const iDoc = iframe.contentDocument;
const scale = iframe.parentElement.offsetWidth / 1920;
['chat', 'alert'].forEach(widget => {
const handle = iDoc.getElementById(`${widget}-handle`);
if (!handle) return;
interact(handle).draggable({
listeners: {
move(event) {
const rect = iDoc.documentElement;
const x = parseFloat(getComputedStyle(handle).left) + event.dx / scale;
const y = parseFloat(getComputedStyle(handle).top) + event.dy / scale;
const left = Math.max(0, Math.min(x / 1920 * 100, 95));
const top = Math.max(0, Math.min(y / 1080 * 100, 95));
if (widget === 'chat') {
iDoc.documentElement.style.setProperty('--chat-left', `${left}%`);
iDoc.documentElement.style.setProperty('--chat-top', `${top}%`);
} else {
iDoc.documentElement.style.setProperty('--alert-left', `${left}%`);
iDoc.documentElement.style.setProperty('--alert-top', `${top}%`);
}
},
end() { savePositions(); }
}
});
});
});
function savePositions() {
const iDoc = iframe.contentDocument;
const get = (v) => parseFloat(getComputedStyle(iDoc.documentElement).getPropertyValue(v));
fetch('/layout/positions', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
chat_left: get('--chat-left') || <%= layout.chat_left %>,
chat_top: get('--chat-top') || <%= layout.chat_top %>,
chat_width: <%= layout.chat_width %>,
chat_height: <%= layout.chat_height %>,
alert_left: get('--alert-left') || <%= layout.alert_left %>,
alert_top: get('--alert-top') || <%= layout.alert_top %>,
}),
});
}
</script>