Skip to content

Commit f035132

Browse files
Keine leere Seite nach Updates, Web 0.3.40 (#143)
* Keine leere Seite nach Updates: alte Assets eine Version behalten, fehlende Dateien einmal neu laden, sonst Hinweis Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XV48YREU9ynsuFLr37cukz * Web-Version 0.3.40 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XV48YREU9ynsuFLr37cukz --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent d91e605 commit f035132

9 files changed

Lines changed: 1070 additions & 986 deletions

File tree

‎.github/scripts/deploy-website.sh‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,17 @@ if ! lftp -c "$connect; get $MANIFEST -o \"$work/old\"" 2>/dev/null; then
108108
: > "$work/old"
109109
fi
110110

111+
# Die Assets des vorigen Builds bleiben eine Version lang liegen: Ein Browser, der noch
112+
# die alte Seite offen oder im Cache hat, findet so seine Skripte (sonst bleibt sie leer).
113+
grep '^app/assets/' "$work/old" | LC_ALL=C sort -u > "$work/keep" || true
114+
111115
# app/assets/ wird von Vite bei jedem Build komplett neu erzeugt (Dateinamen mit
112116
# Hash). Was dort auf dem Server liegt und nicht mehr zum Build gehört, ist veraltet,
113117
# auch wenn es noch von Hand hochgeladen wurde.
114118
lftp -c "$connect; cls -1 app/assets/" 2>/dev/null | sed 's|^.*/||; s|^|app/assets/|' | grep -v '/$' >> "$work/old" || true
115119

116120
# Dateien, die früher hochgeladen wurden und jetzt nicht mehr dazugehören
117-
LC_ALL=C sort -u "$work/old" | LC_ALL=C comm -23 - "$work/new" > "$work/stale"
121+
LC_ALL=C sort -u "$work/old" | LC_ALL=C comm -23 - "$work/new" | LC_ALL=C comm -23 - "$work/keep" > "$work/stale"
118122
: > "$work/rm.lftp"
119123
while IFS= read -r f; do
120124
case "$f" in
@@ -154,3 +158,9 @@ put "$work/htaccess" -o .htaccess
154158
put "$work/new" -o $MANIFEST
155159
LFTP
156160
echo "Fertig."
161+
162+
# Kontrolle: Schickt der Server die Cache-Regeln aus .htaccess mit?
163+
for url in "${SITE_URL:-https://visustruct.org}/" "${SITE_URL:-https://visustruct.org}/app/index.html"; do
164+
cc="$(curl -sI "$url" | tr -d '\r' | grep -i '^cache-control:' | cut -d' ' -f2- || true)"
165+
echo "::notice::$url Cache-Control: ${cc:-(keiner)}"
166+
done

‎CHANGELOG.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ The format is loosely inspired by Keep a Changelog.
8282

8383
- **Web, Code live:** the setting “Swing support” is now called “Real Java (with Swing)” in all languages.
8484
- **Web, learning area:** an open lesson shows its number as a badge next to the title, like in the lesson list.
85-
- **Web:** the settings menu shows the version number (now 0.3.39) right next to “About VisuStruct”.
85+
- **Web:** the settings menu shows the version number (now 0.3.40) right next to “About VisuStruct”.
8686
- **Web:** the settings menu (gear) is grouped into sections with headings: Display (text size, language), Code live (programming language, code keywords), Java (class, main, Swing support; only shown when Java is selected) and About VisuStruct at the bottom.
8787
- **Web:** toolbar buttons are icons with tooltips. The top bar keeps New, Open, Save and Settings; undo, clipboard, delete, export, code and simulation moved into a toolbar above the Elements and diagram columns. Run and Stop in Code live are icons too.
8888
- **Web:** Column widths are freely adjustable: with the diagram collapsed, Learning and Code live share the width at a draggable divider; with all three open, Learning and Code live can be dragged wider until the diagram keeps 240 px.

‎web/package-lock.json‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎web/package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "visustruct-web",
33
"private": true,
4-
"version": "0.3.39",
4+
"version": "0.3.40",
55
"type": "module",
66
"scripts": {
77
"dev": "vite",

‎web/src/main.ts‎

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,62 @@ import { App, applyCanvasStubTexts } from './ui/app'
33
import { installTooltips } from './ui/tooltip'
44
import { preferredLanguage, setCodeKeywords, setLanguage, storedCodeKeywords } from './ui/i18n'
55

6+
// Nach einem Update kann eine noch offene oder zwischengespeicherte Seite Dateien der alten Version
7+
// nachladen wollen, die es nicht mehr gibt. Dann einmal neu laden statt leer zu bleiben.
8+
const reloadKey = 'visustruct.reloadedAfterError'
9+
10+
function reloadOnce(): boolean {
11+
try {
12+
const last = Number(sessionStorage.getItem(reloadKey))
13+
if (last && Date.now() - last < 30_000) return false
14+
sessionStorage.setItem(reloadKey, String(Date.now()))
15+
} catch {
16+
return false
17+
}
18+
location.reload()
19+
return true
20+
}
21+
22+
/** Statt einer leeren Seite: kurzer Hinweis mit Knopf zum Neuladen (Texte fest, die Übersetzungen fehlen ja evtl.). */
23+
function showStartupError(error: unknown) {
24+
console.error(error)
25+
const de = (navigator.language || '').toLowerCase().startsWith('de')
26+
const box = document.createElement('div')
27+
box.className = 'startup-error'
28+
const title = document.createElement('h1')
29+
title.textContent = de ? 'VisuStruct konnte nicht starten' : 'VisuStruct could not start'
30+
const text = document.createElement('p')
31+
text.textContent = de
32+
? 'Wahrscheinlich gibt es gerade eine neue Version. Lade die Seite neu. Hilft das nicht, drücke Strg+Umschalt+R (Mac: ⌘⇧R).'
33+
: 'There is probably a new version. Reload the page. If that does not help, press Ctrl+Shift+R (Mac: ⌘⇧R).'
34+
const button = document.createElement('button')
35+
button.textContent = de ? 'Neu laden' : 'Reload'
36+
button.addEventListener('click', () => location.reload())
37+
const detail = document.createElement('pre')
38+
detail.textContent = String(error instanceof Error ? error.message : error)
39+
box.append(title, text, button, detail)
40+
;(document.getElementById('app') ?? document.body).replaceWith(box)
41+
}
42+
43+
window.addEventListener('vite:preloadError', (event) => {
44+
if (reloadOnce()) event.preventDefault()
45+
})
46+
647
// Erst die Sprache (sie übernimmt ein altes „Java (Keywords)“), dann den Schalter Code-Keywords.
748
const language = preferredLanguage()
8-
void Promise.all([setLanguage(language, false), setCodeKeywords(storedCodeKeywords(), false)]).then(() => {
9-
applyCanvasStubTexts()
10-
installTooltips()
11-
new App(document.getElementById('app')!)
12-
})
49+
Promise.all([setLanguage(language, false), setCodeKeywords(storedCodeKeywords(), false)])
50+
.then(() => {
51+
applyCanvasStubTexts()
52+
installTooltips()
53+
new App(document.getElementById('app')!)
54+
try {
55+
sessionStorage.removeItem(reloadKey)
56+
} catch {
57+
/* egal */
58+
}
59+
})
60+
.catch((error: unknown) => {
61+
// Fehlende Datei nach einem Update: einmal neu laden, sonst Hinweis zeigen.
62+
if (/dynamically imported module|Importing a module script failed|error loading dynamically/i.test(String(error)) && reloadOnce()) return
63+
showStartupError(error)
64+
})

‎web/src/ui/styles.css‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3210,3 +3210,25 @@ button.danger-text:not(:disabled) {
32103210
.learn-mark.gruen {
32113211
background: #dcfce7;
32123212
}
3213+
3214+
/* Hinweis statt leerer Seite, wenn die App nicht starten konnte (main.ts) */
3215+
.startup-error {
3216+
max-width: 520px;
3217+
margin: 15vh auto 0;
3218+
padding: 0 16px;
3219+
font: 16px/1.5 system-ui, -apple-system, sans-serif;
3220+
color: var(--text);
3221+
}
3222+
.startup-error h1 {
3223+
font-size: 22px;
3224+
}
3225+
.startup-error button {
3226+
font-size: 16px;
3227+
padding: 8px 16px;
3228+
}
3229+
.startup-error pre {
3230+
margin-top: 24px;
3231+
color: var(--muted);
3232+
font-size: 12px;
3233+
white-space: pre-wrap;
3234+
}
Lines changed: 973 additions & 973 deletions
Large diffs are not rendered by default.
Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎website/app/index.html‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<title>VisuStruct Web</title>
77
<meta name="description" content="VisuStruct im Browser: Struktogramme nach Nassi-Shneiderman erstellen, simulieren und als Java, Python oder JavaScript ausgeben. Dateien bleiben auf deinem Gerät." />
88
<link rel="icon" type="image/png" href="data:image/png;base64,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" />
9-
<script type="module" crossorigin src="./assets/index-Cz9Fo9zD.js"></script>
10-
<link rel="stylesheet" crossorigin href="./assets/index-CmgDRnXe.css">
9+
<script type="module" crossorigin src="./assets/index-D05tJOQz.js"></script>
10+
<link rel="stylesheet" crossorigin href="./assets/index-DdxaLIVP.css">
1111
</head>
1212
<body>
1313
<div id="app"></div>

0 commit comments

Comments
 (0)