Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion shared/lib/shield.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { DAY } from '../constants/time';

const SUBSCRIPTION_ENDING_SOON_DAYS = DAY;

function getShieldSubscription(
export function getShieldSubscription(
subscriptions: Subscription | Subscription[],
): Subscription | undefined {
let shieldSubscription: Subscription | undefined;
Expand Down
13 changes: 12 additions & 1 deletion ui/components/app/shield-entry-modal/shield-entry-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,14 @@ import { getShouldSubmitEventsForShieldEntryModal } from '../../../selectors';

// TODO: Fix in https://github.com/MetaMask/metamask-extension/issues/31860
// eslint-disable-next-line @typescript-eslint/naming-convention
export default function ShieldEntryModal() {
export default function ShieldEntryModal({
// Whether to skip event submission (e.g., when opened from a user action)
skipEventSubmission = false,
onClose,
}: {
skipEventSubmission?: boolean;
onClose?: () => void;
}) {
const t = useI18nContext();
const dispatch = useDispatch();
const navigate = useNavigate();
Expand All @@ -47,6 +54,10 @@ export default function ShieldEntryModal() {
);

const handleOnClose = () => {
if (skipEventSubmission) {
onClose?.();
return;
}
if (shouldSubmitEvent) {
dispatch(
submitSubscriptionUserEvents({
Expand Down
20 changes: 17 additions & 3 deletions ui/pages/settings/settings.component.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import {
import { SnapIcon } from '../../components/app/snaps/snap-icon';
import { SnapSettingsRenderer } from '../../components/app/snaps/snap-settings-page';
import PasswordOutdatedModal from '../../components/app/password-outdated-modal';
import ShieldEntryModal from '../../components/app/shield-entry-modal';
import SettingsTab from './settings-tab';
import AdvancedTab from './advanced-tab';
import InfoTab from './info-tab';
Expand Down Expand Up @@ -97,6 +98,7 @@ class SettingsPage extends PureComponent {
backRoute: PropTypes.string,
conversionDate: PropTypes.number,
currentPath: PropTypes.string,
hasShieldSubscription: PropTypes.bool,
isAddressEntryPage: PropTypes.bool,
isMetaMaskShieldFeatureEnabled: PropTypes.bool,
isPasswordChangePage: PropTypes.bool,
Expand All @@ -122,6 +124,7 @@ class SettingsPage extends PureComponent {
lastFetchedConversionDate: null,
searchResults: [],
searchText: '',
showShieldEntryModal: false,
};

componentDidMount() {
Expand Down Expand Up @@ -184,6 +187,12 @@ class SettingsPage extends PureComponent {
},
)}
>
{this.state.showShieldEntryModal && (
<ShieldEntryModal
skipEventSubmission
onClose={() => this.setState({ showShieldEntryModal: false })}
/>
)}
{isSeedlessPasswordOutdated && <PasswordOutdatedModal />}
<Box
className="settings-page__header"
Expand Down Expand Up @@ -377,6 +386,7 @@ class SettingsPage extends PureComponent {
useExternalServices,
settingsPageSnaps,
isMetaMaskShieldFeatureEnabled,
hasShieldSubscription,
} = this.props;
const { t } = this.context;

Expand Down Expand Up @@ -472,11 +482,15 @@ class SettingsPage extends PureComponent {
}
return matchPath(key, currentPath);
}}
onSelect={(key) =>
onSelect={(key) => {
if (key === TRANSACTION_SHIELD_ROUTE && !hasShieldSubscription) {
this.setState({ showShieldEntryModal: true });
return;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Shield Subscription Status Blocks Access Modal

The condition !hasShieldSubscription prevents the modal from showing for users with paused, cancelled, or past_due subscriptions. Since getHasShieldSubscription returns true for any subscription regardless of status, users with inactive subscriptions won't see the entry modal but also can't access the Transaction Shield page, leaving them unable to manage their subscription.

Fix in Cursor Fix in Web

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User with existing shield subscription should redirect to Transaction Shield page. We have different UI inside Transaction Shield page to show those states

navigate(key, {
state: { fromPage: currentPath },
})
}
});
}}
/>
);
}
Expand Down
2 changes: 2 additions & 0 deletions ui/pages/settings/settings.container.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { getSnapName } from '../../helpers/utils/util';
import { decodeSnapIdFromPathname } from '../../helpers/utils/snaps';
import { getIsSeedlessPasswordOutdated } from '../../ducks/metamask/metamask';
import { getIsMetaMaskShieldFeatureEnabled } from '../../../shared/modules/environment';
import { getHasShieldSubscription } from '../../selectors/subscription/subscription';
import Settings from './settings.component';

const ROUTES_TO_I18N_KEYS = {
Expand Down Expand Up @@ -176,6 +177,7 @@ const mapStateToProps = (state, ownProps) => {
backRoute,
conversionDate,
currentPath: pathname,
hasShieldSubscription: getHasShieldSubscription(state),
isAddressEntryPage,
isMetaMaskShieldFeatureEnabled: getIsMetaMaskShieldFeatureEnabled(),
isPasswordChangePage,
Expand Down
12 changes: 11 additions & 1 deletion ui/selectors/subscription/subscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import {
Subscription,
SubscriptionControllerState,
} from '@metamask/subscription-controller';
import { getIsShieldSubscriptionActive } from '../../../shared/lib/shield';
import {
getIsShieldSubscriptionActive,
getShieldSubscription,
} from '../../../shared/lib/shield';

export type SubscriptionState = {
metamask: SubscriptionControllerState & {
Expand Down Expand Up @@ -49,3 +52,10 @@ export function getLastUsedShieldSubscriptionPaymentDetails(
): CachedLastSelectedPaymentMethod | undefined {
return state.metamask.lastSelectedPaymentMethod?.[PRODUCT_TYPES.SHIELD];
}

export function getHasShieldSubscription(state: SubscriptionState): boolean {
const shieldSubscription = getShieldSubscription(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this logic right @tuna1207 @lwin-kyaw

we don't wanna show the modal if the user has subscribed to shield atleast once

state.metamask.subscriptions,
);
return Boolean(shieldSubscription);
}
Loading