diff --git a/HILFE.md b/HILFE.md
index fb80093..eb51c76 100644
--- a/HILFE.md
+++ b/HILFE.md
@@ -2,7 +2,16 @@
Willkommen beim Typewriter Trainer! Diese Hilfe erklärt alle Funktionen und gibt Tipps für effektives Tipptraining.
-
+
+
+
---
@@ -422,6 +431,8 @@ Der Text scrollt **automatisch**, sodass:
- 🚀 **Produktivität**: Bis zu 3x schneller tippen
- 🧠 **Weniger Ermüdung**: Ergonomischer für Ihre Hände
+---
+
**Viel Erfolg beim Training!** 💪
---
diff --git a/README.md b/README.md
index 8f353e7..c42b3b6 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-# 🎹 Typewriter Tutor - Adaptiver Tipptrainer
+# Typewriter Tutor - Adaptiver Tipptrainer
-**Version:** v0.3.0 _(siehe [VERSION](VERSION) Datei)_
+**Version:** v0.4.0 _(siehe [VERSION](VERSION) Datei)_
Ein moderner, webbasierter Tipptrainer mit **adaptivem Metronom** und umfangreichen Statistiken. Das Programm passt sich automatisch Ihrer Tippgeschwindigkeit an und hilft Ihnen, das Zehnfingerschreiben systematisch zu erlernen.
@@ -369,7 +369,12 @@ Contributions sind willkommen! Bitte:
> **Hinweis:** Die aktuelle Versionsnummer wird zentral in der [VERSION](VERSION) Datei verwaltet.
-### Version 0.3.0 (Aktuell)
+### Version 0.4.0 (Aktuell)
+- ✅ **Landing Page**: Begrüßungsseite mit Übersicht über Funktionen und direktem Zugang zum Training
+- ✅ **Theme-Integration**: Dark/Light Mode Toggle auch auf der Landing Page
+- ✅ **Verbesserte Navigation**: Zentrale Einstiegsseite für neue Nutzer
+
+### Version 0.3.0
- ✅ **Maximale Metronom-Geschwindigkeit**: Konfigurierbar (Standard: 100 BPM) zur Vermeidung von Überforderung
- ✅ **Präzisions-Anzeige**: Positive Darstellung (Präzision statt Fehlerrate) für motivierendes Feedback
- ✅ **Persistente Settings**: Einstellungen werden in Datenbank gespeichert (nicht nur Session)
diff --git a/VERSION b/VERSION
index 1d0ba9e..a423f7f 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.4.0
+v0.4.5
diff --git a/static/css/style.css b/static/css/style.css
index d66a1d8..ebd6f84 100644
--- a/static/css/style.css
+++ b/static/css/style.css
@@ -120,6 +120,22 @@ body {
color: #a0a0a0; /* Hellgrau für Sonderzeichen */
}
+/* Korrekt eingegebene Whitespace-Zeichen in dezent grau-grün (Dark Mode) */
+[data-bs-theme="dark"] .highlight-correct.highlight-space,
+[data-bs-theme="dark"] .highlight-correct.highlight-tab,
+[data-bs-theme="dark"] .highlight-correct.highlight-newline {
+ color: #7fc49a;
+ font-weight: normal;
+}
+
+/* Falsch eingegebene Whitespace-Zeichen in rot (Dark Mode) */
+[data-bs-theme="dark"] .highlight-incorrect.highlight-space,
+[data-bs-theme="dark"] .highlight-incorrect.highlight-tab,
+[data-bs-theme="dark"] .highlight-incorrect.highlight-newline {
+ color: #f87171;
+ font-weight: normal;
+}
+
[data-bs-theme="dark"] .form-control {
background-color: #2d2d2d;
color: #e0e0e0;
@@ -309,13 +325,29 @@ body {
max-width: 900px;
}
-.highlight-space,
-.highlight-tab,
+.highlight-space,
+.highlight-tab,
.highlight-newline {
color: #888;
font-weight: normal;
}
+/* Korrekt eingegebene Whitespace-Zeichen in dezent grau-grün */
+.highlight-correct.highlight-space,
+.highlight-correct.highlight-tab,
+.highlight-correct.highlight-newline {
+ color: #6ca87f;
+ font-weight: normal;
+}
+
+/* Falsch eingegebene Whitespace-Zeichen in rot */
+.highlight-incorrect.highlight-space,
+.highlight-incorrect.highlight-tab,
+.highlight-incorrect.highlight-newline {
+ color: #dc3545;
+ font-weight: normal;
+}
+
@media (max-width: 768px) {
.container {
padding: 0 10px;
diff --git a/images/Quertz_10_Finger_Layout.jpg b/static/images/Quertz_10_Finger_Layout.jpg
similarity index 100%
rename from images/Quertz_10_Finger_Layout.jpg
rename to static/images/Quertz_10_Finger_Layout.jpg
diff --git a/static/images/typing_hands.jpg b/static/images/typing_hands.jpg
new file mode 100644
index 0000000..7ec3c3a
Binary files /dev/null and b/static/images/typing_hands.jpg differ
diff --git a/static/js/main.js b/static/js/main.js
index 12d4eee..05cf9e9 100644
--- a/static/js/main.js
+++ b/static/js/main.js
@@ -33,6 +33,9 @@ class TypewriterApp {
this.metronomeMode = 'automatic';
this.targetErrorRate = 5;
this.speedDisplay = 'zpm';
+
+ // Time display update interval
+ this.timeDisplayInterval = null;
}
/**
@@ -70,6 +73,9 @@ class TypewriterApp {
this.metronomePlayer.start();
}
+ // Start time display update interval (updates every second)
+ this.startTimeDisplayUpdate();
+
console.log('Typewriter Tutor initialized successfully');
}
@@ -315,6 +321,35 @@ class TypewriterApp {
}
}
+ /**
+ * Start the time display update interval
+ * Updates every second to show running time
+ */
+ startTimeDisplayUpdate() {
+ // Clear any existing interval
+ if (this.timeDisplayInterval) {
+ clearInterval(this.timeDisplayInterval);
+ }
+
+ // Update every second
+ this.timeDisplayInterval = setInterval(() => {
+ // Only update if not paused
+ if (!this.sessionManager.isPaused) {
+ this.updateTrainingTimeDisplay();
+ }
+ }, 1000);
+ }
+
+ /**
+ * Stop the time display update interval
+ */
+ stopTimeDisplayUpdate() {
+ if (this.timeDisplayInterval) {
+ clearInterval(this.timeDisplayInterval);
+ this.timeDisplayInterval = null;
+ }
+ }
+
/**
* Update text display
* @param {boolean} isKeystroke - Whether this is triggered by a keystroke
@@ -490,6 +525,9 @@ class TypewriterApp {
* End session
*/
async endSession() {
+ // Stop time display update
+ this.stopTimeDisplayUpdate();
+
try {
const settings = {
metronome_enabled: this.metronomePlayer.enabled,
diff --git a/static/js/textDisplay.js b/static/js/textDisplay.js
index a8dbb49..77cd8f4 100644
--- a/static/js/textDisplay.js
+++ b/static/js/textDisplay.js
@@ -81,11 +81,26 @@ export class TextDisplayManager {
const escapedChar = this.escapeHtml(char);
if (char === ' ') {
- return `·`;
+ if (type === 'incorrect' && incorrectChar !== null) {
+ const escapedIncorrectChar = this.escapeHtml(incorrectChar);
+ return `·`;
+ } else {
+ return `·`;
+ }
} else if (char === '\t') {
- return `→`;
+ if (type === 'incorrect' && incorrectChar !== null) {
+ const escapedIncorrectChar = this.escapeHtml(incorrectChar);
+ return `→`;
+ } else {
+ return `→`;
+ }
} else if (char === '\n') {
- return `↵
`;
+ if (type === 'incorrect' && incorrectChar !== null) {
+ const escapedIncorrectChar = this.escapeHtml(incorrectChar);
+ return `↵
`;
+ } else {
+ return `↵
`;
+ }
} else {
if (type === 'incorrect' && incorrectChar !== null) {
const escapedIncorrectChar = this.escapeHtml(incorrectChar);
diff --git a/templates/hilfe.html b/templates/hilfe.html
index decfde0..1b89bd9 100644
--- a/templates/hilfe.html
+++ b/templates/hilfe.html
@@ -4,7 +4,7 @@