From 669aabf5f24e6d3be950b8a0714dfa944a144665 Mon Sep 17 00:00:00 2001 From: David Keane Date: Wed, 27 May 2026 02:40:06 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20mode-aware=20WPM=20ceiling=20=E2=80=94?= =?UTF-8?q?=20Sentence/Paragraph=20now=20go=20up=20to=203000=20WPM=20(v1.1?= =?UTF-8?q?.1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The WPM slider's maximum value now adapts to the active reading mode: - Word mode: 1500 WPM ceiling (human single-word recognition limit) - Sentence / Paragraph modes: 3000 WPM ceiling Rationale: in chunk modes, "WPM" controls auto-advance timing across larger display units. A 20-word sentence at 3000 WPM still gets ~400 ms of display time — well within visual-recognition comfort and suitable for skim-pass reading of already-familiar material. Switching back to Word mode auto-clamps the current value down to 1500 to prevent accidentally-illegible word-mode playback. The `+` keyboard shortcut now respects the mode-specific ceiling instead of being hardcoded to 1500. --- CHANGELOG.md | 19 +++++++++++++++++++ ranger-reader.html | 19 +++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a92f07e..755733c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,25 @@ Format: [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/) — versi --- +## [1.1.1] — 2026-05-27 + +### Changed — Mode-aware WPM ceiling + +The WPM slider's maximum value now adapts to the active reading mode: + +- **Word** mode: 1500 WPM ceiling (human single-word recognition limit — beyond ~25 ms per word the brain stops registering individual words) +- **Sentence** and **Paragraph** modes: 3000 WPM ceiling. In chunk modes the "WPM" controls auto-advance timing across larger display units, so higher values still produce comprehensible reading speeds (a 20-word sentence at 3000 WPM still gets ~400 ms of display time, which is well within visual-recognition comfort) + +Switching from a high-WPM chunk mode back to Word mode automatically clamps the current value down to 1500, preventing accidentally-illegible word-mode playback. + +The `+` keyboard shortcut now respects the mode-specific ceiling. + +### Why this matters + +For skim-pass reading on long thesis papers, the previous 1500 WPM cap in Sentence mode was too conservative. With a 20-word sentence at 1500 WPM the display held each sentence for ~1 s — comfortable but slower than necessary for already-known territory. 3000 WPM cuts that to ~400 ms, suitable for the Preview / Postview phases of structured reading (preview chapters, scan for known concepts, identify sections that warrant a slower second-pass read). + +--- + ## [1.1.0] — 2026-05-27 ### Added — Sentence and Paragraph reading modes diff --git a/ranger-reader.html b/ranger-reader.html index 277ff87..54c0139 100644 --- a/ranger-reader.html +++ b/ranger-reader.html @@ -250,7 +250,7 @@ textarea:focus { Paste text below, drag a .txt file in, then press Play - v1.1 + v1.1.1
@@ -513,11 +513,26 @@ textarea:focus { } // ─── Mode switching ──────────────────────────────────────────── + // Mode-aware WPM ceiling. Word mode caps at 1500 — beyond that, the + // brain can't register single words faster than ~25ms per word. But + // Sentence and Paragraph modes display whole chunks at once; "WPM" + // there controls auto-advance timing, so values up to 3000 are + // genuinely useful for skim-reading (a 20-word sentence at 3000 WPM + // still gets ~400ms of display, which is comprehensible). + const WPM_MAX = { word: 1500, sentence: 3000, paragraph: 3000 }; + function applyMode() { stage.className = `stage mode-${mode}`; [...modeToggle.querySelectorAll('button')].forEach(b => { b.classList.toggle('active', b.dataset.mode === mode); }); + // Adjust the WPM ceiling for the current mode + clamp current value if it exceeds + const newMax = WPM_MAX[mode] || 1500; + wpmSlider.max = newMax; + if (parseInt(wpmSlider.value) > newMax) { + wpmSlider.value = newMax; + wpmVal.textContent = newMax; + } } function setMode(newMode) { if (newMode === mode) return; @@ -567,7 +582,7 @@ textarea:focus { else if (k === '2') { setMode('sentence'); } else if (k === '3') { setMode('paragraph'); } else if (k === '+' || k === '=') { - wpmSlider.value = Math.min(1500, parseInt(wpmSlider.value) + 50); + wpmSlider.value = Math.min(parseInt(wpmSlider.max), parseInt(wpmSlider.value) + 50); wpmVal.textContent = wpmSlider.value; updateMeta(); save();