fix: load sections too

backup
flop 3 weeks ago
parent d1c042922b
commit 256fde9214
  1. 98
      ts/index.html

@ -406,7 +406,7 @@
flex-shrink: 0
}
/* red × section & element */
/* red × - section & element */
.x-btn {
background: none;
border: none;
@ -681,11 +681,11 @@
<div id="sec-meta">
<div class="meta-row">
<label>Selected section</label>
<span class="meta-val green" id="meta-name"></span>
<span class="meta-val green" id="meta-name">-</span>
</div>
<div class="meta-row">
<label>Elements</label>
<span class="meta-val" id="meta-count"></span>
<span class="meta-val" id="meta-count">-</span>
</div>
<div class="meta-row">
<label>Section flags</label>
@ -728,7 +728,7 @@
let currentFilename = 'untitled';
let isDirty = false;
// ─── Element type definitions ────────────────────────────────────────────────
// --- Element type definitions ------------------------------------------------
const EL_TYPES = ['Image2D', 'Animation', 'ClippedText', 'HScrollText', 'CurrentTime'];
const EL_FIELDS = {
Image2D: [
@ -746,7 +746,7 @@
{ k: 'width', l: 'Width', t: 'number', d: W }, { k: 'height', l: 'Height', t: 'number', d: 16 },
],
HScrollText: [
{ k: 'text', l: 'Text', t: 'text', d: 'Scrolling text ', full: true },
{ k: 'text', l: 'Text', t: 'text', d: 'Scrolling text - ', full: true },
{ k: 'xOffset', l: 'X offset', t: 'number', d: 0 }, { k: 'yOffset', l: 'Y offset', t: 'number', d: 32 },
{ k: 'width', l: 'Width', t: 'number', d: W }, { k: 'height', l: 'Height', t: 'number', d: 16 },
{ k: 'scrollSpeed', l: 'Scroll speed', t: 'number', d: 50 },
@ -763,7 +763,7 @@
CurrentTime: [{ k: 'clock12h', l: '12h mode' }, { k: 'showHours', l: 'Show hours' }, { k: 'showSeconds', l: 'Show seconds' }],
};
// ─── Confirm dialog ───────────────────────────────────────────────────────────
// --- Confirm dialog -----------------------------------------------------------
function confirm(msg, buttons) {
// buttons: [{label,primary,action}]
return new Promise(resolve => {
@ -782,7 +782,7 @@
});
}
// ─── Dirty tracking ───────────────────────────────────────────────────────────
// --- Dirty tracking -----------------------------------------------------------
function markDirty() {
isDirty = true;
document.getElementById('filename').classList.add('dirty');
@ -800,7 +800,7 @@
return action;
}
// ─── Helpers ─────────────────────────────────────────────────────────────────
// --- Helpers -----------------------------------------------------------------
function newSec() {
secCounter++;
return {
@ -819,7 +819,7 @@
function getSec(id) { return sections.find(s => s.id === id) }
function getEl(secId, elId) { const s = getSec(secId); return s && s.elements.find(e => e.id === elId) }
// ─── Mutations ────────────────────────────────────────────────────────────────
// --- Mutations ----------------------------------------------------------------
function addSection() {
const s = newSec(); sections.push(s);
activeSec = s.id; activeEl = null;
@ -871,7 +871,7 @@
el.flags[key] = val; markDirty(); triggerPreview();
}
// ─── Load demo into editor state ─────────────────────────────────────────────
// --- Load demo into editor state ---------------------------------------------
const DEMO_DEFS = [
{
label: 'Checkerboard', build() {
@ -900,7 +900,7 @@
label: 'Scrolltext', build() {
const s = newSec(); s.name = 'Scrolltext'; s.flags = { drawFront: true, clearBuffer: true };
const el = newEl('HScrollText');
el.fields.text = 'MONO DISPLAY — scrolling ticker — 🚀 ';
el.fields.text = 'MONO DISPLAY - scrolling ticker - 🚀 ';
el.fields.yOffset = 32; el.fields.scrollSpeed = 50;
el.flags.endless = true; el.flags.invertDirection = false;
s.elements.push(el); return [s];
@ -925,7 +925,7 @@
},
];
// ─── Preview via MonoDisplayFile (same as original demos) ────────────────────
// --- Preview via MonoDisplayFile (same as original demos) --------------------
const DEMO_PREVIEWS = {
Checkerboard() {
const { MonoDisplayFile, ElementType } = window.MonoDisplay;
@ -963,7 +963,7 @@
elements_always: {
flags: { drawFront: true, clearBuffer: true },
elements: [{
type: ElementType.HScrollText, text: 'MONO DISPLAY — scrolling ticker — 🚀 ',
type: ElementType.HScrollText, text: 'MONO DISPLAY - scrolling ticker - 🚀 ',
xOffset: 0, yOffset: 32, width: W, height: 16, scrollSpeed: 50, flags: { endless: true, invertDirection: false }
}]
}
@ -1011,7 +1011,7 @@
});
}
// ─── Render ───────────────────────────────────────────────────────────────────
// --- Render -------------------------------------------------------------------
function render() {
updateMeta();
const wrap = document.getElementById('sections-wrap');
@ -1085,20 +1085,20 @@
}
function elSummary(el) {
if (el.fields.text) return esc(el.fields.text.slice(0, 24) + (el.fields.text.length > 24 ? '' : ''));
if (el.fields.text) return esc(el.fields.text.slice(0, 24) + (el.fields.text.length > 24 ? '...' : ''));
return `${el.fields.xOffset ?? 0}, ${el.fields.yOffset ?? 0}`;
}
function esc(s) { return String(s).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') }
function updateMeta() {
const s = activeSec ? getSec(activeSec) : null;
document.getElementById('meta-name').textContent = s ? s.name : '';
document.getElementById('meta-count').textContent = s ? s.elements.length + ' element(s)' : '';
document.getElementById('meta-name').textContent = s ? s.name : '-';
document.getElementById('meta-count').textContent = s ? s.elements.length + ' element(s)' : '-';
document.getElementById('flag-drawFront').checked = s ? !!s.flags.drawFront : false;
document.getElementById('flag-clearBuffer').checked = s ? !!s.flags.clearBuffer : false;
}
// ─── Preview ──────────────────────────────────────────────────────────────────
// --- Preview ------------------------------------------------------------------
let previewTimer = null;
function triggerPreview() {
clearTimeout(previewTimer);
@ -1120,17 +1120,69 @@
));
}
// ─── Load / Export ────────────────────────────────────────────────────────────
// --- Load / Export ------------------------------------------------------------
function parsedToSections(parsedSecs) {
const TYPE_MAP = { 1: 'Image2D', 2: 'Animation', 16: 'ClippedText', 17: 'HScrollText', 32: 'CurrentTime' };
return parsedSecs
.filter(s => s.sectionType === 1 || s.sectionType === 2)
.map(s => {
secCounter++;
const elements = (s.elements || []).map(el => {
const typeName = TYPE_MAP[el.type];
if (!typeName) return null;
elCounter++;
let fields = {}, flags = {};
switch (typeName) {
case 'Image2D':
fields = { xOffset: el.xOffset, yOffset: el.yOffset, width: el.image?.width ?? W, height: el.image?.height ?? H };
break;
case 'Animation':
fields = { xOffset: el.xOffset, yOffset: el.yOffset, width: el.width, height: el.height, updateInterval: el.updateInterval };
break;
case 'ClippedText':
fields = { text: el.text, xOffset: el.xOffset, yOffset: el.yOffset, width: el.width, height: el.height };
break;
case 'HScrollText':
fields = { text: el.text, xOffset: el.xOffset, yOffset: el.yOffset, width: el.width, height: el.height, scrollSpeed: el.scrollSpeed };
flags = { endless: !!el.flags?.endless, invertDirection: !!el.flags?.invertDirection };
break;
case 'CurrentTime':
fields = { xOffset: el.xOffset, yOffset: el.yOffset, width: el.width, height: el.height, utcOffsetMinutes: el.utcOffsetMinutes };
flags = { clock12h: !!el.flags?.clock12h, showHours: !!el.flags?.showHours, showSeconds: !!el.flags?.showSeconds };
break;
}
return { id: 'e' + elCounter, type: typeName, fields, flags };
}).filter(Boolean);
return {
id: 's' + secCounter,
name: 'Section ' + secCounter,
open: true,
flags: { drawFront: !!s.flags?.drawFront, clearBuffer: !!s.flags?.clearBuffer },
elements
};
});
}
function loadBin(input) {
const file = input.files[0]; if (!file) return;
currentFilename = file.name;
document.getElementById('filename').textContent = file.name;
const reader = new FileReader();
reader.onload = e => {
const buf = new Uint8Array(e.target.result);
const arrayBuf = e.target.result;
const buf = new Uint8Array(arrayBuf);
if (!window._mdDriver && window.MonoDisplay)
window._mdDriver = new window.MonoDisplay.MonoDisplayDriver('canvas_root', { onColor: '#EC0', offColor: '#000', fps: 25 });
if (window._mdDriver) window._mdDriver.load(() => Promise.resolve(buf));
try {
const parsed = new window.MonoDisplay.MonoDisplayParser().parse(arrayBuf);
sections = parsedToSections(parsed.sections);
activeSec = sections.length ? sections[0].id : null;
activeEl = null;
render();
} catch (err) {
console.warn('Could not parse sections from bin:', err);
}
};
reader.readAsArrayBuffer(file);
input.value = ''; markClean();
@ -1149,7 +1201,7 @@
a.click(); markClean();
}
// ─── Theme ────────────────────────────────────────────────────────────────────
// --- Theme --------------------------------------------------------------------
var _THEMES = ['dark', 'light', 'auto'];
function _getTheme() { return document.documentElement.getAttribute('data-theme') || 'auto'; }
function _applyTheme(t) {
@ -1172,11 +1224,11 @@
var t = _getTheme(), dr = _detectDR();
var lbl = { dark: '☾ dark', light: '☀ light', auto: '⊙ auto' };
btn.textContent = (dr ? 'DR · ' : '') + (lbl[t] || lbl.auto);
btn.title = dr ? 'DarkReader active controlling theme' : ('Theme: ' + t + ' (click to cycle)');
btn.title = dr ? 'DarkReader active - controlling theme' : ('Theme: ' + t + ' (click to cycle)');
}
window.addEventListener('DOMContentLoaded', _updateThemeBtn);
// ─── Init ─────────────────────────────────────────────────────────────────────
// --- Init ---------------------------------------------------------------------
render();
if (window.MonoDisplay) { initDemos(); }
else { const iv = setInterval(() => { if (window.MonoDisplay) { clearInterval(iv); initDemos(); } }, 100); }

Loading…
Cancel
Save