diff --git a/web/app.react.js b/web/app.react.js
--- a/web/app.react.js
+++ b/web/app.react.js
@@ -42,6 +42,7 @@
import DisconnectedBar from './redux/disconnected-bar';
import DisconnectedBarVisibilityHandler from './redux/disconnected-bar-visibility-handler';
import FocusHandler from './redux/focus-handler.react';
+import PolicyAcknowledgmentHandler from './redux/policy-acknowledgment-handler.js';
import { useSelector } from './redux/redux-utils';
import VisibilityHandler from './redux/visibility-handler.react';
import history from './router-history';
@@ -155,6 +156,7 @@
+
{content}
{this.props.modals}
diff --git a/web/redux/policy-acknowledgment-handler.js b/web/redux/policy-acknowledgment-handler.js
new file mode 100644
--- /dev/null
+++ b/web/redux/policy-acknowledgment-handler.js
@@ -0,0 +1,40 @@
+// @flow
+
+import * as React from 'react';
+
+import { useModalContext } from 'lib/components/modal-provider.react.js';
+import { policyTypes } from 'lib/facts/policies.js';
+
+import TermsAndPrivacyModal from '../modals/terms-and-privacy-modal.react.js';
+import { useSelector } from './redux-utils.js';
+
+function PolicyAcknowledgmentHandler(): null {
+ const [policyModalPushed, setPolicyModalPushed] = React.useState(false);
+ const needPolicyAcceptance = useSelector(store => store.userPolicies);
+ const { pushModal, popModal } = useModalContext();
+
+ React.useEffect(() => {
+ const tosAndPrivacyState =
+ needPolicyAcceptance?.[policyTypes.tosAndPrivacyPolicy];
+ if (!tosAndPrivacyState && policyModalPushed) {
+ popModal();
+ setPolicyModalPushed(false);
+ }
+ if (!tosAndPrivacyState) {
+ return;
+ }
+ const { isAcknowledged } = tosAndPrivacyState;
+ if (!isAcknowledged && !policyModalPushed) {
+ pushModal();
+ setPolicyModalPushed(true);
+ }
+ if (isAcknowledged && policyModalPushed) {
+ popModal();
+ setPolicyModalPushed(false);
+ }
+ }, [needPolicyAcceptance, policyModalPushed, popModal, pushModal]);
+
+ return null;
+}
+
+export default PolicyAcknowledgmentHandler;