feat: Debug-Kasten minimierbar; Mobil-Inhalte ~25 % kleiner
Debug-Panel: Ein Klick entfernte es bisher ganz — was nichts half, weil der 15-Sekunden-Takt es sofort wieder aufbaute; auf dem Telefon verdeckte es damit dauerhaft die untere rechte Ecke. Jetzt schaltet der Klick zwischen Kasten und einem 26-px-Icon (⟳) unten rechts um. Der Zustand liegt im localStorage, nicht am Element: Das Panel wird bei jedem Takt neu bespielt, ein Zustand am DOM-Knoten wäre beim nächsten Tick weg. Über einen echten Intervall-Durchlauf geprüft. Der aufgeklappte Kasten bekommt white-space:pre-wrap — die mit \n gefügten Zeilen liefen bisher zu einem Absatz zusammen. Mobil ~25 % kleiner: MOBILE_ZOOM=0.75 als Faktor AUF den Nutzer-Zoom, nicht als neuer Anfangswert — sonst wäre die Verkleinerung nach dem ersten Zoomen weg und „Zurücksetzen" führte auf eine Größe, die auf dem Telefon zu groß ist. Die Anzeige nennt den effektiven Wert (75 %), sie soll beschreiben was man sieht. Die drei Messstellen rechnen jetzt effZoom() zurück; nachgemessen bei 0,75 liegen alle fünf Stationspunkte exakt auf ihren Blattknoten (0 px). Der Text kann kein zoom bekommen — Zeilennummern-Streifen und Spiegel messen am Textfeld (D33) und die Streifenbreite rechnet in ch. Also font-size .64rem an Textfeld und Streifen gemeinsam, Innenabstand im selben Verhältnis mit. 27 statt 19 Zeilen im Bild. Dabei aufgefallen: Der Grafikexport war schon immer zoom-abhängig falsch — die SVG-Schriftgrößen sind feste Zahlen, die Kästen gemessen. Fiel nie auf, weil 100 % der Normalfall war; mit dem Mobil-Faktor wäre es der Regelfall geworden. diagramToSvg() stellt den Zoom für die Messung jetzt kurz auf 1 (Knoten auf dem Schirm 143 px, im SVG 189,7 px — die unskalierte Größe). Desktop unverändert nachgeprüft (Zoom 1, 100 %, 13,6 px). Prod-Build enthält das Debug-Panel weiterhin gar nicht. SPEC §9, D17 (Nachtrag 2) und frontend/CLAUDE.md nachgezogen. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
ec086eb526
commit
037db30d96
@@ -243,6 +243,54 @@ Mobil, die Grid-Minima `--pmin-d`/`--pmin-e`, `syncPanelMins()`,
|
|||||||
`setMobileDrow()` und das Titelzeilen-Tippen; Desktop behält Splitter,
|
`setMobileDrow()` und das Titelzeilen-Tippen; Desktop behält Splitter,
|
||||||
Presets und Fenster-Buttons unverändert.
|
Presets und Fenster-Buttons unverändert.
|
||||||
|
|
||||||
|
**Nachtrag 2 — auf Mobil sind die Inhalte grundsätzlich ~25 % kleiner, und der
|
||||||
|
Debug-Kasten minimiert sich statt zu verschwinden.**
|
||||||
|
|
||||||
|
**Verkleinerung als Faktor, nicht als neuer Anfangswert.** `MOBILE_ZOOM = 0.75`
|
||||||
|
multipliziert den Nutzer-Zoom (`effZoom()`), statt ihn beim ersten Start auf
|
||||||
|
0,75 zu setzen. Der Unterschied zählt: Ein Anfangswert wäre nach dem ersten
|
||||||
|
Zoomen weg, und „Zurücksetzen" führte zurück auf eine Größe, die auf dem
|
||||||
|
Telefon zu groß ist. Als Faktor bleibt die Verkleinerung eine Eigenschaft des
|
||||||
|
Geräts, und der Regler arbeitet relativ dazu weiter. Die Anzeige nennt den
|
||||||
|
**effektiven** Wert (75 % statt 100 %) — sie soll beschreiben, was man sieht,
|
||||||
|
nicht was man eingestellt hat.
|
||||||
|
|
||||||
|
**Die drei Messstellen mussten mit.** `alignStems()`, `drawCheapPath()` und
|
||||||
|
`drawDepLinks()` rechnen gemessene Pixel durch den CSS-`zoom` zurück; sie lesen
|
||||||
|
jetzt `effZoom()` statt `zoom`. Nachgemessen bei 0,75: alle fünf
|
||||||
|
Stationspunkte liegen exakt (0 px Abweichung) auf ihren Blattknoten.
|
||||||
|
|
||||||
|
**Der Text kann kein `zoom` bekommen.** Zeilennummern-Streifen und Spiegel
|
||||||
|
messen am Textfeld (D33), und der Streifen rechnet seine Breite in `ch` — beide
|
||||||
|
folgen der **Schriftgröße**, nicht einem Zoom auf einem Vorfahren. Also
|
||||||
|
`font-size: .64rem` (= 0,85 × 0,75) an Textfeld **und** Streifen gemeinsam;
|
||||||
|
`line-height` ist einheitenlos und skaliert mit. Der Innenabstand des
|
||||||
|
Textfelds schrumpft im selben Verhältnis mit (14/16 → 10/12 px), sonst wäre der
|
||||||
|
Rand auf 375 px unverhältnismäßig breit. Ergebnis: 27 statt 19 Zeilen im Bild.
|
||||||
|
|
||||||
|
**Dabei aufgefallen: der Grafikexport war schon immer zoom-abhängig falsch.**
|
||||||
|
Die Schriftgrößen im Ausgabe-SVG sind feste Zahlen (14 für Labels, 9–11 für
|
||||||
|
Badges), die Kästen kommen aus der Live-Messung — bei jedem Zoom ≠ 1 passten
|
||||||
|
Text und Kasten nicht zueinander. Das fiel nie auf, weil 100 % der Normalfall
|
||||||
|
war; mit der Mobil-Verkleinerung wäre es der Regelfall geworden. `diagramToSvg()`
|
||||||
|
stellt den Zoom für die Messung deshalb kurz auf 1 und danach zurück —
|
||||||
|
derselbe Griff wie bei der `exporting`-Klasse (D25-Nachtrag), und die Funktion
|
||||||
|
läuft synchron, es wird nichts davon gezeichnet. Nachgemessen: Knoten auf dem
|
||||||
|
Schirm 143 px, im SVG 189,7 px — also die unskalierte Größe, passend zur festen
|
||||||
|
Schrift.
|
||||||
|
|
||||||
|
**Das Debug-Panel minimiert sich jetzt, statt sich zu schließen.** Ein Klick
|
||||||
|
entfernte es bisher ganz — was nichts half, weil der 15-Sekunden-Takt es sofort
|
||||||
|
wieder aufbaute; auf dem Telefon verdeckte es damit dauerhaft die untere rechte
|
||||||
|
Ecke. Jetzt schaltet der Klick zwischen Kasten und einem 26-px-Icon (⟳) unten
|
||||||
|
rechts um. Der Zustand liegt im **localStorage**, nicht am Element: Das Panel
|
||||||
|
wird bei jedem Takt neu bespielt, ein Zustand am DOM-Knoten wäre also beim
|
||||||
|
nächsten Tick weg. Nachgeprüft über einen echten Intervall-Durchlauf und über
|
||||||
|
den `visibilitychange`-Pfad — es bleibt minimiert. (Test-Hilfe, im Prod-Build
|
||||||
|
ohnehin unterdrückt; die Gelegenheit genutzt, dem aufgeklappten Kasten
|
||||||
|
`white-space: pre-wrap` zu geben — die mit `\n` gefügten Zeilen liefen bisher
|
||||||
|
zu einem Absatz zusammen.)
|
||||||
|
|
||||||
## D18 — Günstigsten Pfad per Inversion zeigen, fehlende Größe = M
|
## D18 — Günstigsten Pfad per Inversion zeigen, fehlende Größe = M
|
||||||
Der kostengünstigste Weg durch den Baum wird hervorgehoben (Umschalter im
|
Der kostengünstigste Weg durch den Baum wird hervorgehoben (Umschalter im
|
||||||
Diagramm-Kopf, Default an, Zustand persistiert). Nötig sind bei **all of** alle
|
Diagramm-Kopf, Default an, Zustand persistiert). Nötig sind bei **all of** alle
|
||||||
|
|||||||
+6
-1
@@ -403,7 +403,12 @@ damit genau dann zu sehen, wenn der Text vorn ist. Die übrigen
|
|||||||
umgeschaltet — jeder Bereich zeigt seine eigenen, in der unten beschriebenen
|
umgeschaltet — jeder Bereich zeigt seine eigenen, in der unten beschriebenen
|
||||||
komprimierten Form. Der sichtbare Bereich wird gemerkt; ein Sprung zwischen
|
komprimierten Form. Der sichtbare Bereich wird gemerkt; ein Sprung zwischen
|
||||||
Diagramm und Text (§9) holt den nötigen Bereich selbst nach vorn.
|
Diagramm und Text (§9) holt den nötigen Bereich selbst nach vorn.
|
||||||
Voreinstellung ist das Diagramm. Die **Legende** bekommt hier einen eigenen
|
Voreinstellung ist das Diagramm. Beide Inhalte werden hier zudem rund **25 %
|
||||||
|
kleiner** dargestellt, damit mehr Plan auf die Fläche passt; das ist ein Faktor
|
||||||
|
**auf** den Zoom, der Zoom-Regler arbeitet unverändert relativ dazu und zeigt
|
||||||
|
den effektiven Wert (auf dem Telefon also 75 %). Der **Grafikexport** ist davon
|
||||||
|
unberührt — er zeichnet immer die unskalierte Geometrie nach. Die **Legende**
|
||||||
|
bekommt hier einen eigenen
|
||||||
Umschalter im Editor-Kopf (statt der dauerhaften „AGENDA“-Zeile), damit sie
|
Umschalter im Editor-Kopf (statt der dauerhaften „AGENDA“-Zeile), damit sie
|
||||||
zugeklappt keinen Platz kostet. Der **Modus-Wähler** zeigt nur das aktive Icon
|
zugeklappt keinen Platz kostet. Der **Modus-Wähler** zeigt nur das aktive Icon
|
||||||
und schaltet bei jedem Tippen reihum weiter (horizontal → kompakt → vertikal →
|
und schaltet bei jedem Tippen reihum weiter (horizontal → kompakt → vertikal →
|
||||||
|
|||||||
+13
-1
@@ -395,7 +395,19 @@ verworfene Elemente. Quelle sind ES-Module unter `src/`; `index.html` ist der
|
|||||||
Bereich selbst um: `revealEditor()` auf Text, `focusNodeOfCaret()` aufs
|
Bereich selbst um: `revealEditor()` auf Text, `focusNodeOfCaret()` aufs
|
||||||
Diagramm — **vor** dem Zentrieren. Zustand in `werkbaum-ui` (`mobilePane`),
|
Diagramm — **vor** dem Zentrieren. Zustand in `werkbaum-ui` (`mobilePane`),
|
||||||
Variable oben bei `padView` deklariert (saveUI liest sie).
|
Variable oben bei `padView` deklariert (saveUI liest sie).
|
||||||
`applyLayout` ruft auf Mobil **kein** `applySplit`. Dazu eigener Legenden-Umschalter
|
`applyLayout` ruft auf Mobil **kein** `applySplit`.
|
||||||
|
**Inhalte ~25 % kleiner** (D17-Nachtrag 2): `MOBILE_ZOOM = 0.75` als **Faktor**
|
||||||
|
auf den Nutzer-Zoom — `effZoom()` ist die Wahrheit, die `applyZoom()` setzt und
|
||||||
|
die die drei Messstellen (`alignStems`, `drawCheapPath`, `drawDepLinks`)
|
||||||
|
zurückrechnen; wer dort wieder `zoom` einsetzt, verschiebt Linien und
|
||||||
|
Stationspunkte. `applyMobile()` ruft `applyZoom()` in **beiden** Zweigen, sonst
|
||||||
|
bliebe der Faktor beim Wechsel auf Desktop stehen. Der **Text** bekommt kein
|
||||||
|
`zoom`, sondern `font-size` (Streifen und Textfeld gemeinsam) — Spiegel und
|
||||||
|
`ch`-Breite hängen an der Schriftgröße (D33). **`diagramToSvg()` stellt den
|
||||||
|
Zoom für die Messung auf 1**: Die Schriftgrößen im Ausgabe-SVG sind feste
|
||||||
|
Zahlen, die Kästen gemessen — bei Zoom ≠ 1 passt sonst beides nicht zusammen
|
||||||
|
(galt schon vorher, wurde durch den Mobil-Faktor nur zum Regelfall).
|
||||||
|
Dazu eigener Legenden-Umschalter
|
||||||
(`#legendBtn`), schlanke Sprachwahl, Download-Overlay; Default Vollbild +
|
(`#legendBtn`), schlanke Sprachwahl, Download-Overlay; Default Vollbild +
|
||||||
Diagramm maximiert. Layout-CSS hängt an `body.mobile`, nicht an einer eigenen
|
Diagramm maximiert. Layout-CSS hängt an `body.mobile`, nicht an einer eigenen
|
||||||
`@media`-Regel — beide Seiten müssen denselben 640-px-Schwellwert nutzen
|
`@media`-Regel — beide Seiten müssen denselben 640-px-Schwellwert nutzen
|
||||||
|
|||||||
+58
-27
@@ -259,7 +259,7 @@ function applyOptStairs(){
|
|||||||
function alignStems(){
|
function alignStems(){
|
||||||
out.querySelectorAll('ul.and>li').forEach(li => li.style.removeProperty('--stem-x'));
|
out.querySelectorAll('ul.and>li').forEach(li => li.style.removeProperty('--stem-x'));
|
||||||
if(out.classList.contains('vertical') || out.classList.contains('kompakt')) return;
|
if(out.classList.contains('vertical') || out.classList.contains('kompakt')) return;
|
||||||
const z = zoom || 1;
|
const z = effZoom() || 1;
|
||||||
/* `li.opt-group` (Treppe) hat keinen eigenen Knoten — der Stiel zielt auf den
|
/* `li.opt-group` (Treppe) hat keinen eigenen Knoten — der Stiel zielt auf den
|
||||||
ERSTEN Knoten der Kaskade. */
|
ERSTEN Knoten der Kaskade. */
|
||||||
out.querySelectorAll('ul.and>li.has-or, ul.and>li.opt-group').forEach(li => {
|
out.querySelectorAll('ul.and>li.has-or, ul.and>li.opt-group').forEach(li => {
|
||||||
@@ -277,7 +277,7 @@ function drawCheapPath(){
|
|||||||
const leaves = [...out.querySelectorAll('.node.cheap-leaf')]; /* Dokument-Reihenfolge = Lese-Reihenfolge */
|
const leaves = [...out.querySelectorAll('.node.cheap-leaf')]; /* Dokument-Reihenfolge = Lese-Reihenfolge */
|
||||||
if(leaves.length < 2) return;
|
if(leaves.length < 2) return;
|
||||||
const outRect = out.getBoundingClientRect();
|
const outRect = out.getBoundingClientRect();
|
||||||
const z = zoom || 1;
|
const z = effZoom() || 1;
|
||||||
if(!outRect.width || !outRect.height) return; /* Panel eingeklappt */
|
if(!outRect.width || !outRect.height) return; /* Panel eingeklappt */
|
||||||
const pts = leaves.map(el => {
|
const pts = leaves.map(el => {
|
||||||
const r = el.getBoundingClientRect();
|
const r = el.getBoundingClientRect();
|
||||||
@@ -366,7 +366,7 @@ function drawDepLinks(){
|
|||||||
if(!edges.length) return;
|
if(!edges.length) return;
|
||||||
const outRect = out.getBoundingClientRect();
|
const outRect = out.getBoundingClientRect();
|
||||||
if(!outRect.width || !outRect.height) return; /* Panel eingeklappt */
|
if(!outRect.width || !outRect.height) return; /* Panel eingeklappt */
|
||||||
const z = zoom || 1;
|
const z = effZoom() || 1;
|
||||||
const rect = el => { const r = el.getBoundingClientRect();
|
const rect = el => { const r = el.getBoundingClientRect();
|
||||||
return {x:(r.left - outRect.left)/z, y:(r.top - outRect.top)/z,
|
return {x:(r.left - outRect.left)/z, y:(r.top - outRect.top)/z,
|
||||||
w:r.width/z, h:r.height/z,
|
w:r.width/z, h:r.height/z,
|
||||||
@@ -405,6 +405,15 @@ function diagramToSvg(){
|
|||||||
Klasse statt durch Abnehmen von `.current`/`.pulse` — so reißt der Export
|
Klasse statt durch Abnehmen von `.current`/`.pulse` — so reißt der Export
|
||||||
keine laufende Puls-Animation ab und startet sie hinterher nicht neu. */
|
keine laufende Puls-Animation ab und startet sie hinterher nicht neu. */
|
||||||
out.classList.add('exporting');
|
out.classList.add('exporting');
|
||||||
|
/* Zoom für die Messung auf 1 stellen. Die Schriftgrößen im Ausgabe-SVG sind
|
||||||
|
feste Zahlen (14 für Labels, 9–11 für Badges), die Kästen kommen dagegen
|
||||||
|
aus der Messung — bei jedem Zoom ≠ 1 passten Text und Kasten also nicht
|
||||||
|
zueinander. Das fiel bisher kaum auf, weil 100 % der Normalfall war; mit
|
||||||
|
der Mobil-Verkleinerung (D17-Nachtrag 2) wäre es der Regelfall geworden.
|
||||||
|
Derselbe Griff wie bei `exporting`: kurz neutralisieren, hinterher zurück —
|
||||||
|
die Funktion läuft synchron, es wird nichts davon gezeichnet. */
|
||||||
|
const zoomBefore = out.style.zoom;
|
||||||
|
out.style.zoom = 1;
|
||||||
const treeRect = out.getBoundingClientRect();
|
const treeRect = out.getBoundingClientRect();
|
||||||
const PAD = 24;
|
const PAD = 24;
|
||||||
const W = Math.ceil(treeRect.width) + PAD*2;
|
const W = Math.ceil(treeRect.width) + PAD*2;
|
||||||
@@ -581,6 +590,7 @@ function diagramToSvg(){
|
|||||||
});
|
});
|
||||||
|
|
||||||
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${W}" height="${H}" viewBox="0 0 ${W} ${H}" font-family="'IBM Plex Sans',system-ui,sans-serif">${parts.join('')}</svg>`;
|
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${W}" height="${H}" viewBox="0 0 ${W} ${H}" font-family="'IBM Plex Sans',system-ui,sans-serif">${parts.join('')}</svg>`;
|
||||||
|
out.style.zoom = zoomBefore;
|
||||||
out.classList.remove('exporting');
|
out.classList.remove('exporting');
|
||||||
return {svg, W, H};
|
return {svg, W, H};
|
||||||
}
|
}
|
||||||
@@ -1166,6 +1176,14 @@ const ZMIN = 0.3, ZMAX = 3, ZSTEP = 0.1;
|
|||||||
const ZOOM_COLLAPSE_DELAY = 3000; /* 3 Sekunden */
|
const ZOOM_COLLAPSE_DELAY = 3000; /* 3 Sekunden */
|
||||||
let zoom = 1;
|
let zoom = 1;
|
||||||
let zoomCollapseTimeout;
|
let zoomCollapseTimeout;
|
||||||
|
/* Auf kleinem Bildschirm wird der Inhalt grundsätzlich verkleinert (~25 %),
|
||||||
|
damit mehr Plan auf die Fläche passt (D17-Nachtrag 2). Das ist ein Faktor
|
||||||
|
AUF den Nutzer-Zoom, kein neuer Anfangswert: Wer hineinzoomt, tut das
|
||||||
|
weiterhin relativ hierzu. Der Text bekommt dieselbe Verkleinerung über die
|
||||||
|
Schriftgröße (style.css) — CSS-`zoom` verbietet sich dort, weil der
|
||||||
|
Zeilennummern-Streifen und der Spiegel am Textfeld messen (D33). */
|
||||||
|
const MOBILE_ZOOM = 0.75;
|
||||||
|
function effZoom(){ return zoom * (isMobile() ? MOBILE_ZOOM : 1); }
|
||||||
|
|
||||||
function resetZoomCollapseTimeout(){
|
function resetZoomCollapseTimeout(){
|
||||||
const zoomctl = document.querySelector('.zoomctl');
|
const zoomctl = document.querySelector('.zoomctl');
|
||||||
@@ -1179,8 +1197,11 @@ function resetZoomCollapseTimeout(){
|
|||||||
|
|
||||||
function applyZoom(){
|
function applyZoom(){
|
||||||
zoom = Math.min(ZMAX, Math.max(ZMIN, Math.round(zoom * 100) / 100));
|
zoom = Math.min(ZMAX, Math.max(ZMIN, Math.round(zoom * 100) / 100));
|
||||||
out.style.zoom = zoom;
|
out.style.zoom = effZoom();
|
||||||
document.getElementById('zoomReset').textContent = Math.round(zoom * 100) + ' %';
|
/* Angezeigt wird der EFFEKTIVE Wert — die Anzeige soll beschreiben, was man
|
||||||
|
sieht. Auf Mobil steht dort also 75 %, und das erklärt die Verkleinerung,
|
||||||
|
statt sie als „100 %" zu behaupten. */
|
||||||
|
document.getElementById('zoomReset').textContent = Math.round(effZoom() * 100) + ' %';
|
||||||
resetZoomCollapseTimeout();
|
resetZoomCollapseTimeout();
|
||||||
saveUI();
|
saveUI();
|
||||||
}
|
}
|
||||||
@@ -2959,6 +2980,7 @@ function applyMobile(){
|
|||||||
ausgeblendet — die Regeln hängen zwar an `body.mobile`, aber ein
|
ausgeblendet — die Regeln hängen zwar an `body.mobile`, aber ein
|
||||||
stehengebliebener Zustand ist beim nächsten Verkleinern verwirrend. */
|
stehengebliebener Zustand ist beim nächsten Verkleinern verwirrend. */
|
||||||
document.body.classList.remove('pane-diagram', 'pane-text');
|
document.body.classList.remove('pane-diagram', 'pane-text');
|
||||||
|
applyZoom(); /* Mobil-Faktor wieder herausrechnen (D17-Nachtrag 2) */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* Genau ein Bereich (D17-Nachtrag): kein Desktop-Collapse, keine Aufteilung.
|
/* Genau ein Bereich (D17-Nachtrag): kein Desktop-Collapse, keine Aufteilung.
|
||||||
@@ -2967,6 +2989,7 @@ function applyMobile(){
|
|||||||
clearCollapse();
|
clearCollapse();
|
||||||
app.style.removeProperty('--drow');
|
app.style.removeProperty('--drow');
|
||||||
applyMobilePane();
|
applyMobilePane();
|
||||||
|
applyZoom(); /* Mobil-Faktor an-/abschalten (D17-Nachtrag 2) */
|
||||||
/* Default Vollbild auf kleinem Bildschirm — nur ohne gespeicherte Wahl. */
|
/* Default Vollbild auf kleinem Bildschirm — nur ohne gespeicherte Wahl. */
|
||||||
if(!hadStoredUI && !document.body.classList.contains('fullscreen')){
|
if(!hadStoredUI && !document.body.classList.contains('fullscreen')){
|
||||||
document.body.classList.add('fullscreen');
|
document.body.classList.add('fullscreen');
|
||||||
@@ -3127,36 +3150,44 @@ function logUpdate(msg){
|
|||||||
localStorage.setItem('werkbaum-update-log', log.join('\n'));
|
localStorage.setItem('werkbaum-update-log', log.join('\n'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Debug-Panel anzeigen (Test-Hilfe; im Prod-Build unterdrückt) */
|
/* Debug-Panel anzeigen (Test-Hilfe; im Prod-Build unterdrückt).
|
||||||
|
Ein Klick **minimiert** es auf ein Icon unten rechts, ein weiterer holt es
|
||||||
|
zurück. Vorher entfernte der Klick es ganz — das half nichts, weil der
|
||||||
|
15-Sekunden-Takt es gleich wieder aufbaute; auf dem Telefon verdeckte es so
|
||||||
|
dauerhaft die untere rechte Ecke. Der Zustand liegt im localStorage, nicht am
|
||||||
|
Element: Das Panel wird bei jedem Takt neu bespielt und überlebt so auch ein
|
||||||
|
Neuladen. */
|
||||||
|
const LS_DEBUG_MIN = 'werkbaum-update-debug-min';
|
||||||
|
function paintUpdateDebug(panel){
|
||||||
|
const min = localStorage.getItem(LS_DEBUG_MIN) === '1';
|
||||||
|
panel.style.cssText =
|
||||||
|
'position:fixed;bottom:10px;right:10px;z-index:999;' +
|
||||||
|
'background:rgba(0,0,0,0.9);color:#0F766E;border:1px solid #0F766E;' +
|
||||||
|
'font-family:monospace;cursor:pointer;' +
|
||||||
|
(min
|
||||||
|
? 'width:26px;height:26px;padding:0;border-radius:50%;font-size:14px;' +
|
||||||
|
'display:flex;align-items:center;justify-content:center;overflow:hidden;'
|
||||||
|
: 'padding:12px;border-radius:4px;font-size:11px;max-width:240px;' +
|
||||||
|
'max-height:120px;overflow-y:auto;white-space:pre-wrap;');
|
||||||
|
panel.title = 'Update Debug Panel – Klick zum ' + (min ? 'Aufklappen' : 'Minimieren');
|
||||||
|
const log = localStorage.getItem('werkbaum-update-log') || '';
|
||||||
|
panel.textContent = min ? '⟳'
|
||||||
|
: (log ? log.split('\n').slice(-6).join('\n') : 'Keine Einträge');
|
||||||
|
}
|
||||||
function showUpdateDebug(){
|
function showUpdateDebug(){
|
||||||
if(isProdBuild) return;
|
if(isProdBuild) return;
|
||||||
let panel = document.getElementById('updateDebugPanel');
|
let panel = document.getElementById('updateDebugPanel');
|
||||||
if(!panel){
|
if(!panel){
|
||||||
panel = document.createElement('div');
|
panel = document.createElement('div');
|
||||||
panel.id = 'updateDebugPanel';
|
panel.id = 'updateDebugPanel';
|
||||||
panel.style.cssText = `
|
|
||||||
position: fixed;
|
|
||||||
bottom: 10px;
|
|
||||||
right: 10px;
|
|
||||||
background: rgba(0,0,0,0.9);
|
|
||||||
color: #0F766E;
|
|
||||||
padding: 12px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-size: 11px;
|
|
||||||
font-family: monospace;
|
|
||||||
max-width: 240px;
|
|
||||||
max-height: 120px;
|
|
||||||
overflow-y: auto;
|
|
||||||
z-index: 999;
|
|
||||||
border: 1px solid #0F766E;
|
|
||||||
cursor: pointer;
|
|
||||||
`;
|
|
||||||
panel.title = 'Update Debug Panel – Klick zum Schließen';
|
|
||||||
document.body.appendChild(panel);
|
document.body.appendChild(panel);
|
||||||
panel.addEventListener('click', () => panel.remove());
|
panel.addEventListener('click', () => {
|
||||||
|
const min = localStorage.getItem(LS_DEBUG_MIN) !== '1';
|
||||||
|
try{ localStorage.setItem(LS_DEBUG_MIN, min ? '1' : '0'); }catch(_){}
|
||||||
|
paintUpdateDebug(panel);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const log = localStorage.getItem('werkbaum-update-log') || '';
|
paintUpdateDebug(panel);
|
||||||
panel.textContent = log ? log.split('\n').slice(-6).join('\n') : 'Keine Einträge';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset-Button im Header neben Fullscreen (Test-Hilfe; im Prod-Build weggelassen) */
|
/* Reset-Button im Header neben Fullscreen (Test-Hilfe; im Prod-Build weggelassen) */
|
||||||
|
|||||||
@@ -1078,6 +1078,16 @@
|
|||||||
Editor-Kopf tut das weiterhin der Dokumenten-Wähler daneben. */
|
Editor-Kopf tut das weiterhin der Dokumenten-Wähler daneben. */
|
||||||
body.mobile .panetoggle{display:inline-flex}
|
body.mobile .panetoggle{display:inline-flex}
|
||||||
body.mobile .panel.right .panetoggle{margin-right:auto}
|
body.mobile .panel.right .panetoggle{margin-right:auto}
|
||||||
|
/* Inhalte rund 25 % kleiner, damit mehr Plan auf die Fläche passt
|
||||||
|
(D17-Nachtrag 2). Das Diagramm macht das über den CSS-`zoom` (Faktor auf
|
||||||
|
den Nutzer-Zoom, siehe MOBILE_ZOOM in app.js); der Text über die
|
||||||
|
Schriftgröße — `zoom` verbietet sich hier, weil Zeilennummern-Streifen und
|
||||||
|
Spiegel am Textfeld messen (D33) und der Streifen seine Breite in `ch`
|
||||||
|
rechnet. Beide müssen dieselbe Typografie tragen, sonst wandern die Zahlen
|
||||||
|
weg; `line-height` ist einheitenlos und skaliert von selbst mit. */
|
||||||
|
body.mobile textarea,
|
||||||
|
body.mobile .lineno{font-size:.64rem}
|
||||||
|
body.mobile textarea{padding:10px 12px}
|
||||||
/* Untertitel: Kurzfassung, garantiert einzeilig (Ellipsis als Sicherung) */
|
/* Untertitel: Kurzfassung, garantiert einzeilig (Ellipsis als Sicherung) */
|
||||||
body.mobile .sub-full{display:none}
|
body.mobile .sub-full{display:none}
|
||||||
body.mobile .sub-short{display:inline}
|
body.mobile .sub-short{display:inline}
|
||||||
|
|||||||
Reference in New Issue
Block a user