All notable changes to Streaming Message Reader are documented here.
The format is based on Keep a Changelog, and this project uses Semantic Versioning.
- Date stamp leaking into spoken body —
DATE_REwas using\bword boundaries, which silently fail when the Angular DOM renders inline elements without whitespace separators (e.g."AliceMay 20"). Boundaries removed; the\s+\d{1,2}suffix is already specific enough to avoid false positives. - Last-name/badge residue in body —
normalizeMsgnow strips each individual word of the sender's full name from the body start (catches the case where full-name stripping fails because another fragment precedes it), then strips any leading badge words. This closes the loop on messages still read asFirstName Month Day FullName message.
1.8.0 - 2026-05-19
- Project renamed from
message-readertostreaming-message-reader. Script file renamed tostreaming-message-reader.user.js.@name,@namespace, console prefix ([Streaming Message Reader]), and window guard flag (__streamingMessageReaderLoaded) updated accordingly. - GitHub repository renamed to
sbcmsbgithub/streaming-message-reader. localStoragekey intentionally kept asmessage_reader_config_v1so existing users retain their settings.
1.7.5 - 2026-05-18
readSendernow defaults tofalse— only the message body is spoken. The sender name toggle remains available in settings for users who want it.
- Catch-all name prefix strip — added a final regex in
normalizeMsgthat removes any"Name: "or"First Last: "pattern left at the start of the body after all sender-specific stripping passes. This covers the case where VTF injects the username directly into the message body element in a format none of the targeted strips caught.
1.7.4 - 2026-05-18
- Sender name announced twice (
"Alice: Alice: hello everyone") — two separate fixes:stripSenderFromStartnow uses\W*after the sender name instead of a narrow character class ([:·|>-]?). This absorbs any separator (colon, dash, unicode punctuation, etc.) regardless of what the chat UI inserts.- Both extractors and
normalizeMsgnow explicitly try a first-name-only strip after the full-name strip. VTF formats the message body as"FirstName: message"even when the sender element contains the full name, so stripping just"Alice Smith"leaves"Alice: hello"in the body. The additional first-name pass removes it.
- Date stamp read aloud before message body — the chat UI injects a date string (e.g. "May 18") into each message element's
innerText. This appeared in the body after timestamp stripping, blocking the sender-name strip and causing spoken output like"Alice May 18 Alice Smith hello". AddedDATE_RE(matchesMonth DayandMonth Day, Yearpatterns) applied in both extractors and innormalizeMsg, so dates are removed before the sender strip runs and before the dedup key is computed.
1.7.3 - 2026-05-18
- URL redaction — any
http://,https://, orwww.link in a message is replaced with "URL posted" before being spoken. The full URL is never read aloud.
1.7.2 - 2026-05-18
- Old messages being re-read repeatedly — two root causes fixed:
- Key mismatch between seeding and live handling: startup seeding computed the dedup key from raw extraction output, but
handleNodeapplied additional body-cleaning (safety-net strips) before computing its key. If those strips changed the body text the keys differed, so VTF's virtual scroller re-adding a DOM node would bypass the dedup check and re-queue the message. Fixed by extracting anormalizeMsg()helper that is called in both places, guaranteeing identical keys. RECENT_MAXtoo small: with a cap of 200, an active session evicted old messages from the dedup set well within a normal trading day. When VTF's virtual scroller re-inserted those DOM nodes they were no longer in the set and were re-read. Cap raised to 5000.
- Key mismatch between seeding and live handling: startup seeding computed the dedup key from raw extraction output, but
1.7.1 - 2026-05-17
- Panel appearing on every browser tab —
allowedUrlsnow defaults tovtf.t3live.cominstead of empty. Fresh installs only show the panel on the intended site. Users can add more sites via the "Allowed sites" field in settings, or clear it to show on all sites.
1.7.0 - 2026-05-16
- URL allowlist — new
allowedUrlssetting (textarea in settings panel). Enter URL keywords or patterns (one per line); the panel only mounts on matching sites. Leave empty to show on all sites. Includes an "+ Add this site" button that appends the current hostname in one click. TS_LEADINGsafety-net regex — strips any bare time (HH:MMwith or without AM/PM) from the very start of the extracted body, catching timestamps thatTS_BAREmissed because they lacked an AM/PM suffix.- Double-announcement safety net in
handleNode— after extraction, re-strips the sender name and any leading timestamp from the body before assembling the spoken string.
- Settings panel starts collapsed — playback controls are always visible; click
▸in the header to expand settings. Reduces visual noise on load. - Rate and Volume sliders are now side by side (2-column grid), saving vertical space.
- Four option checkboxes arranged in a 2×2 grid: Sender name / First name only / Timestamp / Skip own msgs — with shorter labels to fit the compact layout.
- Checkbox labels shortened: "Announce sender name" → "Sender name", "First name only (e.g. …)" → "First name only", "Announce timestamp (e.g. …)" → "Timestamp", "Skip my own messages" → "Skip own msgs".
- Removed all
t3live.comURL references from README, CHANGELOG, CLAUDE.md, and SETUP.md. The project is fully generic. - CLAUDE.md console probe examples updated to match current panel ID (
msg-reader-panel) and guard flag (__messageReaderLoaded). stripSenderFromStartextracted as a named helper to avoid duplicated do-while pattern across VTF and generic extractors.
1.6.0 - 2026-05-14
- Generic site support — now matches
*://*/*; works on any website, not just VTF. Pick any element on the page as the message container using the "Pick Message Area" button. - Generic message extraction — falls back to
extractMessageGenericfor non-VTF elements: looks for sender in<strong>,<b>, and common class-name patterns; strips timestamps; falls back to"name: body"splitting. - Generic auto-detect heuristics —
autoDetectChatContainernow tries common chat/message list CSS class and id patterns when VTF elements are not present. - Generic seeding — when no VTF
app-st-compactmessageelements exist, seeds existing container children as already-spoken so history is not re-read on startup. - Default selector — pre-filled to the VTF main chat path so VTF users need no manual configuration.
- Project renamed from
vtf-message-readertomessage-reader. Script file renamed tomessage-reader.user.js. Panel title, console prefix,@name,@namespace, andlocalStoragekey updated accordingly. - Storage key changed from
vtf_reader_config_v1tomessage_reader_config_v1(existing users will need to re-enter settings once). - Observer now passes any newly added element to
handleNode, which routes to VTF-specific or generic extraction automatically. - UI label "Main Chat container" → "Message container (CSS selector)". "My VTF username" → "My username".
- Picker prompt updated to "Click a message area on the page."
- Ignore-list placeholder no longer contains example names — replaced with "comma-separated usernames".
- Top comment block and internal code comments no longer reference personal example names.
1.5.0 - 2026-05-13
- Ignore list — comma-separated usernames to skip; matches both full and first names. Includes a quick-add input field.
- First-name only toggle — speak "Joshua" instead of "Joshua Lefler" (default: on).
- Announce timestamp toggle — optionally prepend "10:57 AM" to spoken text (default: off).
- Collapsed panel keeps playback controls visible — settings collapse independently of the playback bar.
- Restructured panel HTML into two zones:
.playback(always visible) and.settings(collapsible). - Skip behavior tightened: introduced a generation counter (
utteranceGen) sosynth.cancel()doesn't trigger double-advances via staleonendcallbacks. - Message extraction is more aggressive about removing duplicate sender mentions and stray timestamps anywhere in the body.
- "Name announced twice + time twice" issue caused by VTF rendering the sender label in both the avatar tooltip and the visible name.
1.4.0 - 2026-05-13
- Skip button (
⏭) — cancels the current message and immediately starts the next queued one.
- Playback buttons now disable contextually (Skip is greyed out when nothing is playing or queued).
1.3.0 - 2026-05-13
- Playback controls — Start (
▶), Pause (⏸), Stop (⏹) buttons with state indicator. - Queue counter in the panel header showing pending utterances.
- VTF-specific extraction targeting
<app-st-compactmessage>components. - Badge-word filtering (T3TG, ADMIN, MOD, VIP, PRO, OWNER, STAFF, TEAM).
- Stop now also disables reading of new incoming messages until Start is pressed (matches media-player conventions).
- Test Voice bypasses the enable flag so users can always verify audio.
- UI chrome strings like "Mention", "Private Chat", "User Info" no longer get read as messages.
1.2.0 - 2026-05-13
- Verbose console logging prefixed with
[VTF Reader]for diagnostics. waitForBodypolling so the script defers all setup untildocument.bodyexists.!importanton panel positioning to prevent VTF's CSS from hiding the panel.- Orange border on the panel for visibility.
- Script now runs in the top frame only (
@all-frames false) — previous behavior of injecting into every iframe was causing silent crashes in sub-frames. - All risky operations wrapped in
try/catchwith explicit error logging.
1.1.0 - 2026-05-13
- Site-specific
@matchpatterns for the primary target site. - Auto-detection of the chat container using Angular component patterns and class-name heuristics.
- Retry loop for chat container detection (every 3s until found).
- "Auto-detect" and "Clear Selector" buttons.
- MutationObserver now uses
subtree: trueto handle Angular's re-renders of the message feed.
1.0.0 - 2026-05-13
- Initial release.
- Generic chat-message reader with text-to-speech using the Web Speech API.
- Visual element picker for manually selecting the message container.
- Voice / rate / volume controls.
- Self-skip filter using configured username.
- Floating draggable control panel with collapse toggle.
- Settings persisted to
localStorage.