@zeniai/client-epic-state 5.0.13-beta0ND → 5.0.13-beta1ND

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.
@@ -163,8 +163,7 @@ class SessionManager {
163
163
  const elapsed = Math.floor((Date.now() - this.warningStartTime) / 1000);
164
164
  if (elapsed >= this.config.warningDurationSeconds) {
165
165
  this.secondsRemaining = 0;
166
- this.clearTimer('countdownInterval');
167
- this.warningActive = false;
166
+ this.stop();
168
167
  this.callbacks?.onAutoLogout();
169
168
  }
170
169
  return;
@@ -204,8 +203,10 @@ class SessionManager {
204
203
  const remaining = this.config.warningDurationSeconds - elapsed;
205
204
  if (remaining <= 0) {
206
205
  this.secondsRemaining = 0;
207
- this.clearTimer('countdownInterval');
208
- this.warningActive = false;
206
+ // stop() clears all timers and listeners before the callback fires so
207
+ // no late tick can re-trigger checkIdle → startWarning if the consumer
208
+ // delays or skips the redirect in onAutoLogout.
209
+ this.stop();
209
210
  this.callbacks?.onAutoLogout();
210
211
  }
211
212
  else {
@@ -279,6 +280,17 @@ class SessionManager {
279
280
  this.lastHeartbeatTime = Math.max(this.lastHeartbeatTime, msg.timestamp);
280
281
  this.hadActivitySinceLastHeartbeat = false;
281
282
  }
283
+ // If this tab is showing the warning but another tab is active, dismiss it —
284
+ // the user is clearly still working. Backend session is already being
285
+ // extended by the active tab, so we just reset local state and resume
286
+ // the heartbeat timer that was paused when the warning started.
287
+ if (this.warningActive) {
288
+ this.warningActive = false;
289
+ this.secondsRemaining = 0;
290
+ this.clearTimer('countdownInterval');
291
+ this.callbacks?.onSessionExtended();
292
+ this.startHeartbeat();
293
+ }
282
294
  }
283
295
  clearTimer(name) {
284
296
  const timer = this[name];
@@ -19,6 +19,7 @@ const sessionHeartbeatEpic = (actions$, _, zeniAPI) => actions$.pipe((0, operato
19
19
  return (0, rxjs_1.of)((0, tenantReducer_1.sessionHeartbeatSuccess)(response.data?.expiry ?? ''));
20
20
  }
21
21
  return (0, rxjs_1.of)((0, tenantReducer_1.sessionHeartbeatFailure)(response.status));
22
- }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, tenantReducer_1.sessionHeartbeatFailure)((0, responsePayload_1.createZeniAPIStatus)('Heartbeat failed', 'Session heartbeat API call errored: ' + JSON.stringify(error))))));
22
+ }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, tenantReducer_1.sessionHeartbeatFailure)((0, responsePayload_1.createZeniAPIStatus)('Heartbeat failed', 'Session heartbeat API call errored: ' +
23
+ (error instanceof Error ? error.message : String(error)))))));
23
24
  }));
24
25
  exports.sessionHeartbeatEpic = sessionHeartbeatEpic;
@@ -160,8 +160,7 @@ export class SessionManager {
160
160
  const elapsed = Math.floor((Date.now() - this.warningStartTime) / 1000);
161
161
  if (elapsed >= this.config.warningDurationSeconds) {
162
162
  this.secondsRemaining = 0;
163
- this.clearTimer('countdownInterval');
164
- this.warningActive = false;
163
+ this.stop();
165
164
  this.callbacks?.onAutoLogout();
166
165
  }
167
166
  return;
@@ -201,8 +200,10 @@ export class SessionManager {
201
200
  const remaining = this.config.warningDurationSeconds - elapsed;
202
201
  if (remaining <= 0) {
203
202
  this.secondsRemaining = 0;
204
- this.clearTimer('countdownInterval');
205
- this.warningActive = false;
203
+ // stop() clears all timers and listeners before the callback fires so
204
+ // no late tick can re-trigger checkIdle → startWarning if the consumer
205
+ // delays or skips the redirect in onAutoLogout.
206
+ this.stop();
206
207
  this.callbacks?.onAutoLogout();
207
208
  }
208
209
  else {
@@ -276,6 +277,17 @@ export class SessionManager {
276
277
  this.lastHeartbeatTime = Math.max(this.lastHeartbeatTime, msg.timestamp);
277
278
  this.hadActivitySinceLastHeartbeat = false;
278
279
  }
280
+ // If this tab is showing the warning but another tab is active, dismiss it —
281
+ // the user is clearly still working. Backend session is already being
282
+ // extended by the active tab, so we just reset local state and resume
283
+ // the heartbeat timer that was paused when the warning started.
284
+ if (this.warningActive) {
285
+ this.warningActive = false;
286
+ this.secondsRemaining = 0;
287
+ this.clearTimer('countdownInterval');
288
+ this.callbacks?.onSessionExtended();
289
+ this.startHeartbeat();
290
+ }
279
291
  }
280
292
  clearTimer(name) {
281
293
  const timer = this[name];
@@ -16,5 +16,6 @@ export const sessionHeartbeatEpic = (actions$, _, zeniAPI) => actions$.pipe(filt
16
16
  return of(sessionHeartbeatSuccess(response.data?.expiry ?? ''));
17
17
  }
18
18
  return of(sessionHeartbeatFailure(response.status));
19
- }), catchError((error) => of(sessionHeartbeatFailure(createZeniAPIStatus('Heartbeat failed', 'Session heartbeat API call errored: ' + JSON.stringify(error))))));
19
+ }), catchError((error) => of(sessionHeartbeatFailure(createZeniAPIStatus('Heartbeat failed', 'Session heartbeat API call errored: ' +
20
+ (error instanceof Error ? error.message : String(error)))))));
20
21
  }));