(readSeen);
+
+ React.useEffect(() => {
+ const handler = () => setIsSeen(readSeen());
+ window.addEventListener(EVENT_NAME, handler);
+ // Also pick up cross-tab dismissals.
+ window.addEventListener('storage', handler);
+ return () => {
+ window.removeEventListener(EVENT_NAME, handler);
+ window.removeEventListener('storage', handler);
+ };
+ }, []);
+
+ return is_seen;
+};
diff --git a/src/pages/dashboard/info-panel.tsx b/src/pages/dashboard/info-panel.tsx
index a90de376b..6753a8e55 100644
--- a/src/pages/dashboard/info-panel.tsx
+++ b/src/pages/dashboard/info-panel.tsx
@@ -1,6 +1,7 @@
import React from 'react';
import classNames from 'classnames';
import { observer } from 'mobx-react-lite';
+import { usePositionsBannerSeen } from '@/components/positions-banner/use-positions-banner-seen';
import Modal from '@/components/shared_ui/modal';
import Text from '@/components/shared_ui/text';
import { DBOT_TABS } from '@/constants/bot-contents';
@@ -34,6 +35,11 @@ const InfoPanel = observer(() => {
};
};
+ // Suppress the Welcome / Guide / FAQs panel while the mobile positions-
+ // banner modal is pending, so the upgrade notice gets first attention.
+ const is_positions_banner_seen = usePositionsBannerSeen();
+ const is_positions_banner_pending = !isDesktop && !is_positions_banner_seen;
+
const handleClose = () => {
setInfoPanelVisibility(false);
setIsTourOpen(false);
@@ -41,7 +47,7 @@ const InfoPanel = observer(() => {
};
React.useEffect(() => {
- if (is_tnc_needed) {
+ if (is_tnc_needed || is_positions_banner_pending) {
setIsTourOpen(false);
} else {
if (is_info_panel_visible) {
@@ -50,7 +56,7 @@ const InfoPanel = observer(() => {
setIsTourOpen(false);
}
}
- }, [is_tnc_needed, is_info_panel_visible]);
+ }, [is_tnc_needed, is_positions_banner_pending, is_info_panel_visible]);
const renderInfo = () => (
diff --git a/src/pages/tutorials/dbot-tours/common/tour-start-dialog.tsx b/src/pages/tutorials/dbot-tours/common/tour-start-dialog.tsx
index 25670ee86..deb95963f 100644
--- a/src/pages/tutorials/dbot-tours/common/tour-start-dialog.tsx
+++ b/src/pages/tutorials/dbot-tours/common/tour-start-dialog.tsx
@@ -1,5 +1,6 @@
import React from 'react';
import { observer } from 'mobx-react-lite';
+import { usePositionsBannerSeen } from '@/components/positions-banner/use-positions-banner-seen';
import Dialog from '@/components/shared_ui/dialog';
import Text from '@/components/shared_ui/text';
import { DBOT_TABS } from '@/constants/bot-contents';
@@ -35,9 +36,12 @@ const TourStartDialog = observer(() => {
const tour_dialog_action = getTourDialogAction(!isDesktop);
const [is_tour_open, setIsTourOpen] = React.useState(false);
const is_tnc_needed = useIsTNCNeeded();
+ // Suppress welcome/tour while the mobile positions-banner modal is pending.
+ const is_positions_banner_seen = usePositionsBannerSeen();
+ const is_positions_banner_pending = !isDesktop && !is_positions_banner_seen;
React.useEffect(() => {
- if (is_tnc_needed || is_platform_migrated) {
+ if (is_tnc_needed || is_platform_migrated || is_positions_banner_pending) {
setIsTourOpen(false);
} else {
if (is_tour_dialog_visible) {
@@ -46,7 +50,7 @@ const TourStartDialog = observer(() => {
setIsTourOpen(false);
}
}
- }, [is_tnc_needed, is_platform_migrated, is_tour_dialog_visible]);
+ }, [is_tnc_needed, is_platform_migrated, is_positions_banner_pending, is_tour_dialog_visible]);
const getTourContent = () => {
return (
diff --git a/src/pages/tutorials/dbot-tours/onboarding-tour/onboarding-tour-mobile.tsx b/src/pages/tutorials/dbot-tours/onboarding-tour/onboarding-tour-mobile.tsx
index 6228a05cf..0e9419748 100644
--- a/src/pages/tutorials/dbot-tours/onboarding-tour/onboarding-tour-mobile.tsx
+++ b/src/pages/tutorials/dbot-tours/onboarding-tour/onboarding-tour-mobile.tsx
@@ -1,6 +1,7 @@
import React from 'react';
import classNames from 'classnames';
import { observer } from 'mobx-react-lite';
+import { usePositionsBannerSeen } from '@/components/positions-banner/use-positions-banner-seen';
import ProgressBarTracker from '@/components/shared_ui/progress-bar-tracker';
import Text from '@/components/shared_ui/text';
import { useStore } from '@/hooks/useStore';
@@ -33,6 +34,9 @@ const OnboardingTourMobile = observer(() => {
const test_id = tour_step_key === 8 ? 'finish-onboard-tour' : 'next-onboard-tour';
const hide_prev_button = [1, 2, 8];
const is_tour_active = active_tour === 'onboarding';
+ // Defer the onboarding tour while the mobile positions-banner modal
+ // is pending — the upgrade notice gets first attention.
+ const is_positions_banner_seen = usePositionsBannerSeen();
React.useEffect(() => {
DBOT_ONBOARDING_MOBILE.forEach(data => {
@@ -45,6 +49,7 @@ const OnboardingTourMobile = observer(() => {
}, [tour_step]);
React.useEffect(() => {
+ if (!is_positions_banner_seen) return;
const checkTokenForTour = () => {
const token = getSetting('onboard_tour_token');
if (!token && active_tab === 0) {
@@ -52,9 +57,10 @@ const OnboardingTourMobile = observer(() => {
}
};
checkTokenForTour();
- }, [active_tab, active_tour]);
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [active_tab, active_tour, is_positions_banner_seen]);
- if (!active_tour) {
+ if (!active_tour || !is_positions_banner_seen) {
return null;
}