@me2em/react 1.0.0-rc.2 → 1.0.0-rc.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/react/useSession.ts +31 -1
package/package.json
CHANGED
package/src/react/useSession.ts
CHANGED
|
@@ -43,7 +43,11 @@ export interface UseSessionResult {
|
|
|
43
43
|
* Supports auto-renewal: when `autoRenew` is true (default), a timer
|
|
44
44
|
* fires at half the session TTL to create a fresh session with a new
|
|
45
45
|
* jti (the previous token remains valid until its own expiry, but the
|
|
46
|
-
* lineage identity is preserved through `handle`).
|
|
46
|
+
* lineage identity is preserved through `handle`). Background tabs
|
|
47
|
+
* throttle (clamped wakeups) or fully suspend timers, so on return to
|
|
48
|
+
* visibility the hook additionally renews proactively when the session
|
|
49
|
+
* is already past its half-life point (BL-51) — the overdue timer path
|
|
50
|
+
* alone could leave the first user actions racing an expired session.
|
|
47
51
|
*
|
|
48
52
|
* On unmount, all timers are cleaned up to prevent state updates after
|
|
49
53
|
* the component is gone.
|
|
@@ -149,6 +153,32 @@ export function useSession(
|
|
|
149
153
|
}
|
|
150
154
|
}, [handle, renew]);
|
|
151
155
|
|
|
156
|
+
// BL-51: background tabs throttle (clamped wakeups) or fully
|
|
157
|
+
// suspend timers (Memory Saver, mobile backgrounds), so the half-life
|
|
158
|
+
// setTimeout alone can fire late — or not at all until the tab
|
|
159
|
+
// resumes. When the document becomes visible again and the session
|
|
160
|
+
// is already past its half-life point (expiresAt − ttl/2, the same
|
|
161
|
+
// threshold the timer uses; expired is a superset), renew
|
|
162
|
+
// proactively. renew() clears and reschedules the timer, so the
|
|
163
|
+
// overdue timer cannot double-renew. autoRenew:false opts out
|
|
164
|
+
// entirely, exactly like the timer path.
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
if (!autoRenew || typeof document === 'undefined') return;
|
|
167
|
+
const onVisibilityChange = () => {
|
|
168
|
+
if (document.visibilityState !== 'visible') return;
|
|
169
|
+
const s = session;
|
|
170
|
+
if (!s) return;
|
|
171
|
+
const halfLifePoint = (s.expiresAt - optionsRef.current.ttl / 2) * 1000;
|
|
172
|
+
if (Date.now() >= halfLifePoint) {
|
|
173
|
+
renew();
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
document.addEventListener('visibilitychange', onVisibilityChange);
|
|
177
|
+
return () => {
|
|
178
|
+
document.removeEventListener('visibilitychange', onVisibilityChange);
|
|
179
|
+
};
|
|
180
|
+
}, [autoRenew, renew, session]);
|
|
181
|
+
|
|
152
182
|
return {
|
|
153
183
|
session,
|
|
154
184
|
isLoaded,
|