Skip to content

Commit a3f1450

Browse files
committed
Address A subscription with the name activity_onBurnComplete already exists exception
1 parent 2b42cb6 commit a3f1450

File tree

1 file changed

+25
-12
lines changed

1 file changed

+25
-12
lines changed

special-pages/pages/new-tab/app/protections/components/ProtectionsProvider.js

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ export const ProtectionsContext = createContext({
3030

3131
export const ProtectionsServiceContext = createContext(/** @type {ProtectionsService|null} */ ({}));
3232

33+
/**
34+
* Context for sharing burn complete time across useBlockedCount hooks
35+
* This allows a single subscription to activity_onBurnComplete at the Provider level
36+
*/
37+
export const BurnCompleteTimeContext = createContext(/** @type {import("preact").RefObject<number | null>} */ ({ current: null }));
38+
3339
/**
3440
* A data provider that will use `ProtectionsService` to fetch initial data only
3541
*
@@ -54,6 +60,19 @@ export function ProtectionsProvider(props) {
5460
// subscribe to config updates
5561
useConfigSubscription({ dispatch, service });
5662

63+
// Set up a single subscription to activity_onBurnComplete at the Provider level
64+
// This prevents duplicate subscription errors when multiple useBlockedCount hooks are used
65+
const ntp = useMessaging();
66+
const burnCompleteTimeRef = useRef(/** @type {number | null} */ (null));
67+
68+
useEffect(() => {
69+
if (!ntp) return;
70+
return ntp.messaging.subscribe('activity_onBurnComplete', () => {
71+
// Mark that we should skip animation if next update goes to 0
72+
burnCompleteTimeRef.current = Date.now();
73+
});
74+
}, [ntp]);
75+
5776
// expose a fn for sync toggling
5877
const toggle = useCallback(() => {
5978
service.current?.toggleExpansion();
@@ -69,7 +88,11 @@ export function ProtectionsProvider(props) {
6988

7089
return (
7190
<ProtectionsContext.Provider value={{ state, toggle, setFeed }}>
72-
<ProtectionsServiceContext.Provider value={service.current}>{props.children}</ProtectionsServiceContext.Provider>
91+
<ProtectionsServiceContext.Provider value={service.current}>
92+
<BurnCompleteTimeContext.Provider value={burnCompleteTimeRef}>
93+
{props.children}
94+
</BurnCompleteTimeContext.Provider>
95+
</ProtectionsServiceContext.Provider>
7396
</ProtectionsContext.Provider>
7497
);
7598
}
@@ -96,19 +119,9 @@ export function useService() {
96119
*/
97120
export function useBlockedCount(initial) {
98121
const service = useContext(ProtectionsServiceContext);
99-
const ntp = useMessaging();
122+
const burnCompleteTimeRef = useContext(BurnCompleteTimeContext);
100123
const signal = useSignal(initial);
101124
const skipAnimationSignal = useSignal(false);
102-
const burnCompleteTimeRef = useRef(/** @type {number | null} */ (null));
103-
104-
// Track burn complete events to detect "burn all" scenario
105-
useEffect(() => {
106-
if (!ntp) return;
107-
return ntp.messaging.subscribe('activity_onBurnComplete', () => {
108-
// Mark that we should skip animation if next update goes to 0
109-
burnCompleteTimeRef.current = Date.now();
110-
});
111-
}, [ntp]);
112125

113126
// @todo jingram possibly refactor to include full object
114127
useSignalEffect(() => {

0 commit comments

Comments
 (0)