Skip to content

Commit 2e7ed1a

Browse files
committed
fix hover pause timer
1 parent ce28148 commit 2e7ed1a

2 files changed

Lines changed: 34 additions & 12 deletions

File tree

src/hooks/useNoticeTimer.ts

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,50 +18,65 @@ export default function useNoticeTimer(
1818
const onEventUpdate = useEvent(onUpdate);
1919

2020
const [walking, setWalking] = React.useState(durationMs > 0);
21-
const startTimestampRef = React.useRef<number | null>(null);
2221
const passTimeRef = React.useRef(0);
22+
const lastRafTimeRef = React.useRef<number | null>(null);
2323

2424
function syncPassTime() {
2525
const now = Date.now();
26-
const passedTime = now - (startTimestampRef.current || now);
27-
startTimestampRef.current = now;
28-
passTimeRef.current += passedTime;
26+
const lastRafTime = lastRafTimeRef.current;
27+
28+
if (lastRafTime !== null) {
29+
passTimeRef.current += now - lastRafTime;
30+
}
31+
32+
lastRafTimeRef.current = now;
2933
}
3034

3135
const onPause = React.useCallback(() => {
36+
if (!walking) {
37+
return;
38+
}
39+
3240
syncPassTime();
41+
if (durationMs > 0) {
42+
onEventUpdate(Math.min(passTimeRef.current / durationMs, 1));
43+
}
3344
setWalking(false);
34-
}, []);
45+
}, [durationMs, walking]);
3546

3647
const onResume = React.useCallback(() => {
3748
if (durationMs > 0) {
49+
lastRafTimeRef.current = Date.now();
3850
setWalking(true);
3951
} else {
4052
onEventUpdate(0);
4153
}
42-
}, [durationMs, onEventUpdate]);
54+
}, [durationMs]);
4355

4456
React.useEffect(() => {
4557
if (durationMs <= 0) {
46-
startTimestampRef.current = null;
58+
lastRafTimeRef.current = null;
4759
onEventUpdate(0);
4860
return;
4961
}
5062

51-
syncPassTime();
5263
onEventUpdate(Math.min(passTimeRef.current / durationMs, 1));
5364

5465
if (!walking) {
55-
startTimestampRef.current = null;
5666
return;
5767
}
5868

69+
syncPassTime();
70+
onEventUpdate(Math.min(passTimeRef.current / durationMs, 1));
71+
5972
if (passTimeRef.current >= durationMs) {
6073
onEventUpdate(1);
6174
onEventClose();
6275
return;
6376
}
6477

78+
lastRafTimeRef.current = Date.now();
79+
6580
const timeout = window.setTimeout(() => {
6681
passTimeRef.current = durationMs;
6782
onEventUpdate(1);
@@ -85,14 +100,13 @@ export default function useNoticeTimer(
85100
}
86101
}
87102

88-
startTimestampRef.current = Date.now();
89103
rafId = raf(step);
90104

91105
return () => {
92106
window.clearTimeout(timeout);
93-
raf.cancel(rafId);
107+
raf.cancel(rafId!);
94108
};
95-
}, [durationMs, walking]);
109+
}, [durationMs, trackProgress, walking]);
96110

97111
return [onResume, onPause] as const;
98112
}

tests/index.test.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ describe('Notification.Basic', () => {
273273
it('continue timing after hover', () => {
274274
const { instance } = renderDemo({
275275
duration: 1,
276+
showProgress: true,
276277
});
277278

278279
act(() => {
@@ -291,10 +292,17 @@ describe('Notification.Basic', () => {
291292

292293
// Mouse in should not remove
293294
fireEvent.mouseEnter(document.querySelector('.rc-notification-notice'));
295+
const pausedProgress = document
296+
.querySelector<HTMLProgressElement>('.rc-notification-notice-progress')
297+
.getAttribute('value');
294298
act(() => {
299+
// Elapsed time should not advance while hovering.
295300
vi.advanceTimersByTime(1000);
296301
});
297302
expect(document.querySelector('.test')).toBeTruthy();
303+
expect(
304+
document.querySelector<HTMLProgressElement>('.rc-notification-notice-progress'),
305+
).toHaveAttribute('value', pausedProgress);
298306

299307
// Mouse out should not remove until 500ms later
300308
fireEvent.mouseLeave(document.querySelector('.rc-notification-notice'));

0 commit comments

Comments
 (0)