Repository navigation
fix(MediaRecorder): stop the recording timer when the preview unmounts - #3351
Conversation
useTimeElapsed cleared its interval only on stopCounter() or when it was started with startOnMount. AudioRecordingPreview starts it from the MediaRecorder start/resume events, so a preview unmounted while recording kept updating state every second. Stop the counter on unmount however it was started.
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Counter cleanup and timer tests src/components/MediaRecorder/AudioRecorder/hooks/useTimeElapsed.ts, src/components/MediaRecorder/AudioRecorder/hooks/__tests__/useTimeElapsed.test.ts |
The hook registers stopCounter as an unmount cleanup. Tests check elapsed time and timer cleanup after startOnMount or startCounter. |
Priority:
Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix
Merge Risk: 
Minimal · up to 8a9d5
-
The timer cleanup change is ready to merge.
Pre-merge checks: 
5
-
Full details: Docstring Coverage
-
Explanation
No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2 files.
-
Finishing Touches: 💡 1
-
📝 Generate docstrings
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
🛠️ Fix failing CI checks: 💡
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
|
Size Change: +15 B (0%) Total Size: 904 kB 📦 View Changed
ℹ️ View Unchanged
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3351 +/- ##
==========================================
+ Coverage 88.58% 88.62% +0.04%
==========================================
Files 562 563 +1
Lines 17053 17141 +88
Branches 5224 5247 +23
==========================================
+ Hits 15106 15191 +85
- Misses 1947 1950 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
## [15.0.0-rc.3](v15.0.0-rc.2...v15.0.0-rc.3) (2026-10-28) ### ⚠ BREAKING CHANGES * channel.watch() resolves with the channel instance to use (the channel, or the instance that superseded it), not the server response: read channel.data, channel.state and channel.messagePaginator instead. - channel.watch() sends no query for a channel already watched and loaded unless it asks for options the current watch was not sent with, so it no longer refreshes one: refresh with channel.reload(), load other messages through channel.messagePaginator. - A channel.watch() while another with the same options is in flight joins it instead of sending a request. * **MessageList:** useMessageListScrollManager no longer takes onScrollToTop. Loading older messages keeps the message the reader was looking at in place, also when loading starts at the very top, instead of pinning the newly loaded page to the top. - InfiniteScrollPaginator's loadNextDebounceMs now rate-limits the edge check while scrolling (the first check runs at once, then at most once per loadNextDebounceMs) instead of waiting until scrolling stops for that long. Older and newer pages start loading before the reader reaches the edge. - MessageList and VirtualizedMessageList pass showNotification to NewMessageNotification only when a message from someone else arrives while the list is scrolled up. Being on an older message set no longer shows it; ScrollToLatestMessageButton signals that. - In a channel, ScrollToLatestMessageButton shows the current user's unread count from the channel's read state instead of counting message.new events, so messages a reconnect brought in are included. In a thread it counts new replies from 0. * marker: the removals are v14 API, so the branch has a `fix!:` commit with a `BREAKING CHANGE:` footer, per the AGENTS.md convention. The footer to keep in the squash commit: * `MessageList` no longer accepts `messages`, `hasMore`, `jumpToLatestMessage`, `loadingMoreNewer` or `messageLimit`, and `VirtualizedMessageList` no longer accepts `messages`; the lists render and paginate the message paginator. `CustomClasses.chatContainer` and the `ComponentContext.LoadingErrorIndicator` slot are removed. Inside `ChatView` the channel list no longer renders its own `str-chat <theme>` scope. See ai-docs/v15-breaking-changes.md (BC-019, BC-046, BC-047, BC-073, BC-074). Verification: `yarn lint`, `tsc -p tsconfig.lib.json --noEmit`, `yarn types:scripts`, `yarn validate-translations` and `yarn test` (281 files, 3090 tests) pass. `yarn build`, `validate-cjs`, `validate-esm`, `validate-entry-isolation`, and the tutorial and vite example builds passed before the rebase onto the guides branch, which brought in only docs and the api-surface script. The ai-chatbot example build was not verified: it hung locally in a sandboxed environment. The theme-scope change was not checked visually in a browser. ### UI Changes No intended visual change inside `ChatView`. Outside `ChatView`, the channel list picks up the design tokens again, as in v14. The `MessageList` loading indicator now appears while older messages load. No screenshots: the examples need Stream credentials to run. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Gallery items can display message-specific timestamp overrides. * Reply-count buttons honor a message’s custom thread-opening behavior. * Standalone channel lists now inherit the chat theme, and channel-detail actions use workspace navigation. * `useMessagePaginator` and `useIsCooldownActive` are available from the package entry point. * Message timestamps can render with an explicit message outside a message context. * **Bug Fixes** * Message-list loading indicators and pagination behavior now reflect active page loads more accurately. * Workspace navigation warns when navigation actions are used without a provider. * **Breaking Changes** * Removed legacy message-list props and the `LoadingErrorIndicator` component override slot. <!-- end of auto-generated comment: release notes by coderabbit.ai --> ### Bug Fixes * correct issues found during the comment cleanup ([#3334](#3334)) ([7f87026](7f87026)) * **examples:** translate the voice visualization keys in the vite example ([#3352](#3352)) ([c88ab33](c88ab33)), closes [#3347](#3347) * **MediaRecorder:** stop the recording timer when the preview unmounts ([#3351](#3351)) ([3c8b30a](3c8b30a)) * **MessageList:** keep the reader's place on older pages and count only arrived messages as new ([#3342](#3342)) ([ab00d67](ab00d67)) * remove dead v15 surface and restore v14 behaviors found by the API audit ([#3328](#3328)) ([d721f40](d721f40)), closes [#3327](#3327) [#3305](#3305) [#3237](#3237) ### Features * **ai-components:** add useHeardText for voice-paced text ([#3348](#3348)) ([ec7c956](ec7c956)), closes [#3343](#3343) [#3344](#3344) [#3344](#3344) [#3343](#3343) [#3339](#3339) [#3347](#3347) * **ai-components:** add VoiceWave and VoiceGlow voice-agent visualizations ([#3347](#3347)) ([216d00d](216d00d)), closes [#3339](#3339) [#3339](#3339) [#3339](#3339) ### Refactors * call Channel.watch(), which replaces ensureWatched() in stream-chat ([#3346](#3346)) ([0100d98](0100d98))
|
🎉 This PR is included in version 15.0.0-rc.3 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Goal
Stop the audio recording timer from running after the recording preview unmounts.
useTimeElapsedcleared its 1 s interval only onstopCounter()or when it was started withstartOnMount.AudioRecordingPreviewstarts it from theMediaRecorderstart/resumeevents instead, and its effect cleanup only removes those listeners, so a preview unmounted while recording kept callingsetSecondsElapsedevery second for as long as the page lived.In CI this showed up as a flaky Test job: all tests passed, but the run failed on an unhandled
ReferenceError: window is not definedthrown fromuseTimeElapsed.ts:19when a leaked tick fired afterAudioRecorder.test.tsx's jsdom environment was torn down (https://github.com/GetStream/stream-chat-react/actions/runs/40310070468/job/121528726305).Implementation details
useTimeElapsedgets an unmount cleanup,useEffect(() => stopCounter, [stopCounter]), so the interval is cleared however the counter was started.stopCounteris a stable callback, so the effect runs only on mount and unmount.hooks/__tests__/useTimeElapsed.test.ts(the hook had no tests), with fake timers: it counts once per second afterstartCounter()and stops onstopCounter(); no timer is left after unmount when started withstartOnMount; and no timer is left after unmount when started withstartCounter(). The last one fails without the fix (expected 1 to be +0).release-v14has the same hook and caller, so v14 has the same leak; not ported here.UI Changes
None.
Summary by CodeRabbit