Files
upstream-jitsi-meet/react/features/authentication/middleware.native.ts
upstream-mirror 1d2bfcac0c
Some checks failed
Prosody Plugin Tests / test (push) Failing after 10m11s
Close stale issues and PRs / stale (push) Failing after 1s
snapshot of https://github.com/jitsi/jitsi-meet.git @ fd1749dd28f4138aa80234fc7f311b19aaffa0e7 (2026-09-15)
2026-09-15 15:56:32 +05:00

85 lines
3.3 KiB
TypeScript

import { CONNECTION_ESTABLISHED, CONNECTION_WILL_CONNECT } from '../base/connection/actionTypes';
import { isDialogOpen } from '../base/dialog/functions';
import { SET_JWT } from '../base/jwt/actionTypes';
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
import { APP_STATE_CHANGED } from '../mobile/background/actionTypes';
import { hideLoginRetryDialog, openLoginRetryDialog, setTokenAuthPending } from './actions.native';
import LoginRetryDialog from './components/native/LoginRetryDialog';
import { isTokenAuthEnabled } from './functions.native';
import './middleware.any';
/**
* Middleware that detects the app returning to the foreground while an
* external token authentication is still pending and warns the user that they
* are not connected to the meeting.
*
* Opening {@code tokenAuthUrl} in the system browser is fire-and-forget: if
* the user abandons the login page and switches back to the app, no deep link
* is ever delivered and the app keeps showing the conference screen with no
* connection and no indication of failure. The pending state is tracked with
* an explicit flag (set when the browser is opened, cleared when a new
* connection attempt starts) because the connection-level error state cannot
* be relied upon: on WebSocket deployments the not-authorized failure is
* immediately followed by a connection-dropped failure which resets it.
*
* @param {Store} store - The redux store.
* @returns {Function}
*/
MiddlewareRegistry.register(store => next => action => {
switch (action.type) {
case APP_STATE_CHANGED: {
if (action.appState !== 'active') {
break;
}
const state = store.getState();
const { tokenAuthPending } = state['features/authentication'];
const { conference, room } = state['features/base/conference'];
const { jwt } = state['features/base/jwt'];
// The app is back in the foreground on the conference screen with the
// external login still pending: no conference was joined and no JWT
// has been delivered via a deep link, so the login was abandoned and
// the app is not connected.
if (tokenAuthPending
&& room
&& !conference
&& !jwt
&& isTokenAuthEnabled(state)
&& !isDialogOpen(store, LoginRetryDialog)) {
store.dispatch(openLoginRetryDialog());
}
break;
}
case SET_JWT:
// SET_JWT with no token is the periodic clearing that happens on
// every navigation; only a delivered token completes the login.
if (!action.jwt) {
break;
}
// eslint-disable-next-line no-fallthrough
case CONNECTION_ESTABLISHED:
case CONNECTION_WILL_CONNECT: {
// The external login is no longer pending once the deep link delivers
// a JWT (the room may first land on the prejoin screen, where no
// connection attempt is started yet) or a new connection attempt
// starts.
const { dispatch, getState } = store;
if (getState()['features/authentication'].tokenAuthPending) {
dispatch(setTokenAuthPending(false));
}
if (isDialogOpen(store, LoginRetryDialog)) {
dispatch(hideLoginRetryDialog());
}
break;
}
}
return next(action);
});