From 051d722b2a4fbc9a566a5f07bc0d91daf7868f25 Mon Sep 17 00:00:00 2001 From: Mayank Mittal Date: Wed, 22 Jul 2026 18:48:06 +0530 Subject: [PATCH 1/5] refactor: environment-gate in-dev features instead of team-member whitelist Replace useIsTestUser()/TEST_FEATURES_ALLOW_LIST with isDevFeatureEnabled (!isProduction). In-dev features (mobile-first UI, Stocks, GoodDollar, bank transfer, coming-soon vaults) are now visible on qa/preview builds and hidden from everyone in production, removing the team-member exception. Co-Authored-By: Claude Opus 4.8 (1M context) --- app/(protected)/(tabs)/_layout.tsx | 14 +++---- app/(protected)/(tabs)/card/details.tsx | 37 +++++++++---------- app/(protected)/(tabs)/index.native.tsx | 12 +++--- app/(protected)/(tabs)/index.tsx | 8 ++-- app/(protected)/(tabs)/rewards/index.tsx | 8 ++-- app/(protected)/(tabs)/savings.tsx | 9 ++--- app/(protected)/(tabs)/settings/index.tsx | 6 +-- app/(protected)/_layout.tsx | 2 +- .../AccountCenterDropdown.web.tsx | 6 +-- .../Card/NewCardDetails/ShowDetailsButton.tsx | 2 +- .../DepositToVault/VaultSelectorDropdown.tsx | 7 ++-- components/Home/NewHome/HomeScreenNew.tsx | 4 +- components/Navbar/HeaderBellButton.tsx | 2 +- components/Navbar/HeaderProfileButton.tsx | 2 +- components/Navbar/NavbarMobile.tsx | 11 +++--- .../Rewards/NewRewards/RewardsScreenNew.tsx | 4 +- .../Savings/NewSavings/SavingsScreenNew.tsx | 4 +- components/Savings/SavingVault.tsx | 5 +-- components/Savings/SavingVaultOld.tsx | 5 +-- components/tabBar/NewCustomTabBar.tsx | 2 +- constants/tabs.ts | 10 ++--- hooks/useDepositBuyCryptoOptions.tsx | 7 ++-- hooks/useIsTestUser.ts | 7 ---- hooks/useNav.ts | 5 +-- lib/config.ts | 2 + lib/utils/index.ts | 2 - lib/utils/testFeatures.ts | 22 ----------- 27 files changed, 84 insertions(+), 121 deletions(-) delete mode 100644 hooks/useIsTestUser.ts delete mode 100644 lib/utils/testFeatures.ts diff --git a/app/(protected)/(tabs)/_layout.tsx b/app/(protected)/(tabs)/_layout.tsx index ccd5b8a12..c9d54a697 100644 --- a/app/(protected)/(tabs)/_layout.tsx +++ b/app/(protected)/(tabs)/_layout.tsx @@ -15,11 +15,10 @@ import RewardsTabIcon from '@/components/tabBar/RewardsTabIcon'; import TabBarBackground from '@/components/ui/TabBarBackground'; import { path } from '@/constants/path'; import { useDimension } from '@/hooks/useDimension'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; +import { isDevFeatureEnabled } from '@/lib/config'; export default function TabLayout() { const { isDesktop } = useDimension(); - const isTestUser = useIsTestUser(); return ( (isTestUser ? : ) + ? props => + isDevFeatureEnabled ? : : undefined } backBehavior="history" @@ -179,12 +179,12 @@ export default function TabLayout() { // Pushed white tier-star image, centered in a full-size box so its // icon↔label gap matches the other tabs. tabBarIcon: ({ size }) => , - // Only surface the Rewards tab (and its route) for whitelisted users; - // the whitelisted NewCustomTabBar renders Wallet/Savings/Rewards. - href: isTestUser ? path.REWARDS : null, + // Only surface the Rewards tab (and its route) on qa/preview builds; + // the redesigned NewCustomTabBar renders Wallet/Savings/Rewards. + href: isDevFeatureEnabled ? path.REWARDS : null, }} /> - {isTestUser && ( + {isDevFeatureEnabled && ( state.active); @@ -240,24 +239,24 @@ export default function CardDetails() { shouldRevealDetails={shouldRevealDetails} onCardDetailsLoaded={handleCardDetailsLoaded} provider={provider} - useNewCard={isTestUser} + useNewCard={devFeaturesEnabled} last4={cardLast4} /> ); return ( - // Whitelisted screen renders immediately (never the full-screen loader): the + // The redesigned screen renders immediately (never the full-screen loader): the // card must be laid out right away so the hero transition can measure its // destination and land smoothly. Data fills in as it arrives (balance/last-4 // are usually already warm from the home screen's query). - - {/* Whitelisted screen drops the "Card" heading — the card image is the top - section; public/desktop keep the heading. */} - {!isTestUser && pageHeader} + + {/* The redesigned screen drops the "Card" heading — the card image is the top + section; production/desktop keep the heading. */} + {!devFeaturesEnabled && pageHeader} - - {!isTestUser && } - {isTestUser ? ( + + {!devFeaturesEnabled && } + {devFeaturesEnabled ? ( // Card is the top section, full-bleed (cancel the container's px-4) to // match the home card width. The Show details button peeks out from // behind it (card sits above via z-10). @@ -290,7 +289,7 @@ export default function CardDetails() { onFreezeToggle={handleFreezeToggle} isWithdrawFromCardAllowed={isWithdrawFromCardAllowed} isRain={provider === CardProvider.RAIN} - hideCardDetailsButton={isTestUser} + hideCardDetailsButton={devFeaturesEnabled} /> @@ -541,7 +540,7 @@ interface CardImageSectionProps { shouldRevealDetails: boolean; onCardDetailsLoaded: () => void; provider?: CardProvider | null; - /** Whitelisted screen: render the new VISA Platinum artwork (with code-drawn + /** Redesigned screen: render the new VISA Platinum artwork (with code-drawn * glyph badge + white "reveal" overlay) instead of the legacy card image. */ useNewCard?: boolean; /** Last 4 digits for the glyph badge (new card only). */ @@ -841,7 +840,7 @@ interface CardActionsProps { onFreezeToggle: () => Promise; isWithdrawFromCardAllowed: boolean; isRain: boolean; - /** Hide the circular "Card details" action (whitelisted screen uses a full-row button instead). */ + /** Hide the circular "Card details" action (redesigned screen uses a full-row button instead). */ hideCardDetailsButton?: boolean; } @@ -1096,7 +1095,7 @@ const styles = StyleSheet.create({ opacity: 0.25, }, - // Whitelisted card: extend past the container's px-4 (16px) padding so the + // Redesigned card: extend past the container's px-4 (16px) padding so the // card is as wide as the home screen card. fullBleedCard: { marginHorizontal: -16 }, // The artwork's bottom ~6.5% is transparent drop-shadow. RN resolves % margins diff --git a/app/(protected)/(tabs)/index.native.tsx b/app/(protected)/(tabs)/index.native.tsx index d285acd80..8b2a71531 100644 --- a/app/(protected)/(tabs)/index.native.tsx +++ b/app/(protected)/(tabs)/index.native.tsx @@ -21,13 +21,13 @@ import { useUserTransactions } from '@/hooks/useAnalytics'; import { useCardDetails } from '@/hooks/useCardDetails'; import { useCardStatus } from '@/hooks/useCardStatus'; import { useCurrentGiveaway, useGiveawayCountdown } from '@/hooks/useGiveaway'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; import { MONITORED_COMPONENTS, useRenderMonitor } from '@/hooks/useRenderMonitor'; import { useSpinStatus } from '@/hooks/useSpinWin'; import { useTotalSavingsUSD } from '@/hooks/useTotalSavingsUSD'; import useUser from '@/hooks/useUser'; import { useVaultBalance } from '@/hooks/useVault'; import { useWalletTokens } from '@/hooks/useWalletTokens'; +import { isDevFeatureEnabled } from '@/lib/config'; import { useIntercom } from '@/lib/intercom'; import { SavingMode } from '@/lib/types'; import { formatBalanceUSD, hasCard } from '@/lib/utils'; @@ -40,8 +40,8 @@ import { useUserStore } from '@/store/useUserStore'; * Web keeps its own layout in `index.tsx`; this `.native.tsx` variant is used on * iOS/Android only (resolved by Metro). * - * Whitelisted internal users see the redesigned `HomeScreenNew`; everyone else - * keeps this `LegacyHome`. The gate lives in the default export below. + * qa/preview builds see the redesigned `HomeScreenNew`; production keeps this + * `LegacyHome`. The gate lives in the default export below. */ function LegacyHome() { useRenderMonitor({ componentName: MONITORED_COMPONENTS.HOME_SCREEN }); @@ -197,8 +197,8 @@ function LegacyHome() { } export default function Home() { - // Whitelisted internal team members see the redesigned wallet screen; all - // other users keep the existing design. Native is never desktop. - const showNewHome = useIsTestUser(); + // qa/preview builds see the redesigned wallet screen; production keeps the + // existing design. Native is never desktop. + const showNewHome = isDevFeatureEnabled; return showNewHome ? : ; } diff --git a/app/(protected)/(tabs)/index.tsx b/app/(protected)/(tabs)/index.tsx index 9b6b61ef3..7d98fb804 100644 --- a/app/(protected)/(tabs)/index.tsx +++ b/app/(protected)/(tabs)/index.tsx @@ -24,13 +24,13 @@ import { useCardDetails } from '@/hooks/useCardDetails'; import { useCardStatus } from '@/hooks/useCardStatus'; import { useDimension } from '@/hooks/useDimension'; import { useCurrentGiveaway, useGiveawayCountdown } from '@/hooks/useGiveaway'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; import { MONITORED_COMPONENTS, useRenderMonitor } from '@/hooks/useRenderMonitor'; import { useSpinStatus } from '@/hooks/useSpinWin'; import { useTotalSavingsUSD } from '@/hooks/useTotalSavingsUSD'; import useUser from '@/hooks/useUser'; import { useVaultBalance } from '@/hooks/useVault'; import { useWalletTokens } from '@/hooks/useWalletTokens'; +import { isDevFeatureEnabled } from '@/lib/config'; import { useIntercom } from '@/lib/intercom'; import { SavingMode } from '@/lib/types'; import { fontSize, formatBalanceUSD, hasCard } from '@/lib/utils'; @@ -262,8 +262,8 @@ function LegacyHome() { export default function Home() { const { isDesktop } = useDimension(); - // Whitelisted internal team members on mobile-web see the redesigned wallet - // screen; desktop web and all other users keep the existing design. - const showNewHome = useIsTestUser() && !isDesktop; + // qa/preview builds on mobile-web see the redesigned wallet screen; desktop + // web and production keep the existing design. + const showNewHome = isDevFeatureEnabled && !isDesktop; return showNewHome ? : ; } diff --git a/app/(protected)/(tabs)/rewards/index.tsx b/app/(protected)/(tabs)/rewards/index.tsx index a2729596a..5d6f50207 100644 --- a/app/(protected)/(tabs)/rewards/index.tsx +++ b/app/(protected)/(tabs)/rewards/index.tsx @@ -18,18 +18,18 @@ import { path } from '@/constants/path'; import { TRACKING_EVENTS } from '@/constants/tracking-events'; import { useCardStatus } from '@/hooks/useCardStatus'; import { useDimension } from '@/hooks/useDimension'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; import { useOptInToRewards, useRewardsUserData } from '@/hooks/useRewards'; import { track } from '@/lib/analytics'; +import { isDevFeatureEnabled } from '@/lib/config'; import { hasCard } from '@/lib/utils'; import { useRewards } from '@/store/useRewardsStore'; import { useRewardsWelcomePopupStore } from '@/store/useRewardsWelcomePopupStore'; export default function Rewards() { - // Whitelisted internal team members see the redesigned rewards screen; all - // other users — and every desktop-web user — keep the existing design. + // qa/preview builds see the redesigned rewards screen; production — and every + // desktop-web user — keep the existing design. const { isDesktop } = useDimension(); - const showNew = useIsTestUser() && !isDesktop; + const showNew = isDevFeatureEnabled && !isDesktop; return showNew ? : ; } diff --git a/app/(protected)/(tabs)/savings.tsx b/app/(protected)/(tabs)/savings.tsx index 9eed8b306..cbeb6191e 100644 --- a/app/(protected)/(tabs)/savings.tsx +++ b/app/(protected)/(tabs)/savings.tsx @@ -30,24 +30,23 @@ import { } from '@/hooks/useAnalytics'; import { useDepositCalculations } from '@/hooks/useDepositCalculations'; import { useDimension } from '@/hooks/useDimension'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; import { MONITORED_COMPONENTS, useRenderMonitor } from '@/hooks/useRenderMonitor'; import { useSavingsSummary } from '@/hooks/useSavingsSummary'; import useUser from '@/hooks/useUser'; import { useTotalVaultBalance, useVaultBalance } from '@/hooks/useVault'; import { useVaultExchangeRate } from '@/hooks/useVaultExchangeRate'; import { getAsset } from '@/lib/assets'; -import { ADDRESSES } from '@/lib/config'; +import { ADDRESSES, isDevFeatureEnabled } from '@/lib/config'; import { SavingMode } from '@/lib/types'; import { fontSize, formatNumber } from '@/lib/utils'; import { useDepositStore } from '@/store/useDepositStore'; import { useSavingStore } from '@/store/useSavingStore'; export default function Savings() { - // Whitelisted internal team members see the redesigned savings screen; all - // other users — and every desktop-web user — keep the existing design. + // qa/preview builds see the redesigned savings screen; production — and every + // desktop-web user — keep the existing design. const { isDesktop } = useDimension(); - const showNew = useIsTestUser() && !isDesktop; + const showNew = isDevFeatureEnabled && !isDesktop; return showNew ? : ; } diff --git a/app/(protected)/(tabs)/settings/index.tsx b/app/(protected)/(tabs)/settings/index.tsx index 2c057e6fd..4c7860002 100644 --- a/app/(protected)/(tabs)/settings/index.tsx +++ b/app/(protected)/(tabs)/settings/index.tsx @@ -23,11 +23,11 @@ import { Text } from '@/components/ui/text'; import { path } from '@/constants/path'; import { getTierDisplayName, getTierIcon } from '@/constants/rewards'; import { useDimension } from '@/hooks/useDimension'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; import useNotificationPermissionStatus from '@/hooks/useNotificationPermissionStatus'; import { useRewardsUserData } from '@/hooks/useRewards'; import useUser from '@/hooks/useUser'; import { getAsset } from '@/lib/assets'; +import { isDevFeatureEnabled } from '@/lib/config'; import { RewardsTier } from '@/lib/types'; import { cn, getUserDisplayName } from '@/lib/utils'; @@ -116,8 +116,8 @@ const MobileSettings = () => { const currentTier = rewardsData?.currentTier ?? RewardsTier.CORE; const displayName = getUserDisplayName(user, 18); const [isReferralModalOpen, setIsReferralModalOpen] = useState(false); - // GoodDollar is internal-only: shown only to whitelisted test users. - const canSeeGoodDollar = useIsTestUser(); + // GoodDollar is in development: shown only on qa/preview builds, hidden in production. + const canSeeGoodDollar = isDevFeatureEnabled; const rowGroups: MobileSettingsRow[][] = [ [ diff --git a/app/(protected)/_layout.tsx b/app/(protected)/_layout.tsx index 42d58fff5..c1bfcd740 100644 --- a/app/(protected)/_layout.tsx +++ b/app/(protected)/_layout.tsx @@ -251,7 +251,7 @@ export default function ProtectedLayout() { }} /> - {/* Root-level hero overlay for the card view-transition (whitelisted new + {/* Root-level hero overlay for the card view-transition (redesigned screens only — stays dormant/null otherwise). Mounted above the whole navigator so the card can fly across the home → card/details change. */} diff --git a/components/AccountCenter/AccountCenterDropdown.web.tsx b/components/AccountCenter/AccountCenterDropdown.web.tsx index 7a6bdea3a..0696ed296 100644 --- a/components/AccountCenter/AccountCenterDropdown.web.tsx +++ b/components/AccountCenter/AccountCenterDropdown.web.tsx @@ -7,8 +7,8 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; import useUser from '@/hooks/useUser'; +import { isDevFeatureEnabled } from '@/lib/config'; import { cn } from '@/lib/utils'; import { @@ -30,8 +30,8 @@ const cursorDefaultClassName = const AccountCenterDropdown = () => { const insets = useSafeAreaInsets(); const { handleLogout } = useUser(); - // GoodDollar is internal-only: shown only to whitelisted test users. - const canSeeGoodDollar = useIsTestUser(); + // GoodDollar is in development: shown only on qa/preview builds, hidden in production. + const canSeeGoodDollar = isDevFeatureEnabled; const contentInsets = { top: insets.top, diff --git a/components/Card/NewCardDetails/ShowDetailsButton.tsx b/components/Card/NewCardDetails/ShowDetailsButton.tsx index b45395622..3c4b0dbb8 100644 --- a/components/Card/NewCardDetails/ShowDetailsButton.tsx +++ b/components/Card/NewCardDetails/ShowDetailsButton.tsx @@ -21,7 +21,7 @@ interface ShowDetailsButtonProps { /** * "Show details" / "Hide details" button (lucide eye open/close), replacing the - * small circular "Card details" action for whitelisted users. In `peek` mode it + * small circular "Card details" action on the redesigned screen. In `peek` mode it * slides out from underneath the card image. */ const ShowDetailsButton = ({ diff --git a/components/DepositToVault/VaultSelectorDropdown.tsx b/components/DepositToVault/VaultSelectorDropdown.tsx index 9d7b6791d..6de584aeb 100644 --- a/components/DepositToVault/VaultSelectorDropdown.tsx +++ b/components/DepositToVault/VaultSelectorDropdown.tsx @@ -7,9 +7,9 @@ import { useShallow } from 'zustand/react/shallow'; import { Text } from '@/components/ui/text'; import { VAULTS } from '@/constants/vaults'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; import useVaultDepositConfig from '@/hooks/useVaultDepositConfig'; import { getAsset } from '@/lib/assets'; +import { isDevFeatureEnabled } from '@/lib/config'; import { Vault } from '@/lib/types'; import { getDefaultDepositSelection } from '@/lib/vaults'; import { useDepositStore } from '@/store/useDepositStore'; @@ -31,7 +31,6 @@ const VaultSelectorDropdown = () => { setPrincipalToken: state.setPrincipalToken, })), ); - const isTestUser = useIsTestUser(); const [isOpen, setIsOpen] = useState(false); @@ -62,7 +61,7 @@ const VaultSelectorDropdown = () => { const handleSelect = (index: number) => { const vault = VAULTS[index]; - const isComingSoon = !!vault?.isComingSoon && !isTestUser; + const isComingSoon = !!vault?.isComingSoon && !isDevFeatureEnabled; if (isComingSoon || !vault) return; selectVaultForDeposit(index); @@ -137,7 +136,7 @@ const VaultSelectorDropdown = () => { {VAULTS.map((vault, index) => { const isSelected = vault.name === selectedVault.name; - const isComingSoon = !!vault.isComingSoon && !isTestUser; + const isComingSoon = !!vault.isComingSoon && !isDevFeatureEnabled; return ( { diff --git a/components/Navbar/NavbarMobile.tsx b/components/Navbar/NavbarMobile.tsx index 53d63e6cf..b9690d343 100644 --- a/components/Navbar/NavbarMobile.tsx +++ b/components/Navbar/NavbarMobile.tsx @@ -11,9 +11,9 @@ import { Image } from 'expo-image'; import AccountCenterDropdown from '@/components/AccountCenter/AccountCenterDropdown.native'; import { Text } from '@/components/ui/text'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; import useUser from '@/hooks/useUser'; import { getAsset } from '@/lib/assets'; +import { isDevFeatureEnabled } from '@/lib/config'; import HeaderBellButton from './HeaderBellButton'; import HeaderProfileButton from './HeaderProfileButton'; @@ -48,11 +48,10 @@ const NavbarMobile = ({ topInset = 0, }: NavbarMobileProps) => { const { user } = useUser(); - const isTestUser = useIsTestUser(); - // Whitelisted "glass" header: profile moves to the left, the bell (Activity) - // joins What's-new on the right, and the Solid logo is dropped. Public users - // keep the existing header untouched. - const showNewHeader = isTestUser && !!user; + // Redesigned "glass" header (qa/preview builds): profile moves to the left, the + // bell (Activity) joins What's-new on the right, and the Solid logo is dropped. + // Production keeps the existing header untouched. + const showNewHeader = isDevFeatureEnabled && !!user; const hasBlurTarget = !!blurTarget; const isGlassVisible = hasBlurTarget && !!showDivider; const isTitleVisible = !!title && !!showTitle; diff --git a/components/Rewards/NewRewards/RewardsScreenNew.tsx b/components/Rewards/NewRewards/RewardsScreenNew.tsx index 9a1c5d0ee..a6f21e451 100644 --- a/components/Rewards/NewRewards/RewardsScreenNew.tsx +++ b/components/Rewards/NewRewards/RewardsScreenNew.tsx @@ -16,8 +16,8 @@ import PointsHeadline from './PointsHeadline'; import RewardsSummaryCard from './RewardsSummaryCard'; /** - * Redesigned rewards screen (Apple "glass" style), shown only to whitelisted - * internal users via the dispatcher in rewards/index.tsx. Public users and all + * Redesigned rewards screen (Apple "glass" style), shown only on qa/preview + * builds via the dispatcher in rewards/index.tsx. Production and all * desktop-web users keep the legacy rewards screen. * * Shows the user's CURRENT tier + points, a rewards summary (cashback + diff --git a/components/Savings/NewSavings/SavingsScreenNew.tsx b/components/Savings/NewSavings/SavingsScreenNew.tsx index 2a09ea873..dbee53791 100644 --- a/components/Savings/NewSavings/SavingsScreenNew.tsx +++ b/components/Savings/NewSavings/SavingsScreenNew.tsx @@ -21,8 +21,8 @@ import VaultSavingsSection from './VaultSavingsSection'; import type { ApyByType } from './savingsVaultData'; /** - * Redesigned savings screen (Apple "glass" style), shown only to whitelisted - * internal users via the dispatcher in savings.tsx. Public users and all + * Redesigned savings screen (Apple "glass" style), shown only on qa/preview + * builds via the dispatcher in savings.tsx. Production and all * desktop-web users keep the legacy savings screen. * * Two states share the "Savings Balance" headline + APY pill: diff --git a/components/Savings/SavingVault.tsx b/components/Savings/SavingVault.tsx index 1515d0113..9a49f9988 100644 --- a/components/Savings/SavingVault.tsx +++ b/components/Savings/SavingVault.tsx @@ -15,8 +15,8 @@ import { useMaxAPY } from '@/hooks/useAnalytics'; import { useDimension } from '@/hooks/useDimension'; import { useVaultTotalValue } from '@/hooks/useVaultTotalValue'; import { getAsset } from '@/lib/assets'; +import { isDevFeatureEnabled } from '@/lib/config'; import { Vault } from '@/lib/types'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; import { compactNumberFormat } from '@/lib/utils'; import { useSavingStore } from '@/store/useSavingStore'; @@ -44,8 +44,7 @@ const SavingVault = ({ vault }: SavingVaultProps) => { const { isScreenMedium } = useDimension(); const vaultIndex = VAULTS.findIndex(v => v.name === vault.name); const isSelected = selectedVault === vaultIndex; - const isTestUser = useIsTestUser(); - const isComingSoon = !!vault.isComingSoon && !isTestUser; + const isComingSoon = !!vault.isComingSoon && !isDevFeatureEnabled; const gapHeight = isScreenMedium ? 12 : 0; const iconSizeSelected = isScreenMedium ? 53 : 28; diff --git a/components/Savings/SavingVaultOld.tsx b/components/Savings/SavingVaultOld.tsx index 0d0d70f91..cab009430 100644 --- a/components/Savings/SavingVaultOld.tsx +++ b/components/Savings/SavingVaultOld.tsx @@ -19,8 +19,8 @@ import { useMaxAPY } from '@/hooks/useAnalytics'; import { useDimension } from '@/hooks/useDimension'; import { useVaultTotalValueOld } from '@/hooks/useVaultTotalValueOld'; import { getAsset } from '@/lib/assets'; +import { isDevFeatureEnabled } from '@/lib/config'; import { Vault } from '@/lib/types'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; import { compactNumberFormat } from '@/lib/utils'; import { useSavingStore } from '@/store/useSavingStore'; @@ -48,8 +48,7 @@ const SavingVaultOld = ({ vault }: SavingVaultOldProps) => { const { isScreenMedium } = useDimension(); const vaultIndex = VAULTS.findIndex(v => v.name === vault.name); const isSelected = selectedVault === vaultIndex; - const isTestUser = useIsTestUser(); - const isComingSoon = !!vault.isComingSoon && !isTestUser; + const isComingSoon = !!vault.isComingSoon && !isDevFeatureEnabled; const gapHeight = isScreenMedium ? 12 : 0; const iconSizeSelected = isScreenMedium ? 53 : 28; diff --git a/components/tabBar/NewCustomTabBar.tsx b/components/tabBar/NewCustomTabBar.tsx index 9724d69cf..d54dae1f7 100644 --- a/components/tabBar/NewCustomTabBar.tsx +++ b/components/tabBar/NewCustomTabBar.tsx @@ -94,7 +94,7 @@ function TabButton({ label, icon, isFocused, onPress, onLongPress, onLayout }: T } /** - * Whitelisted "glass" bottom tab bar. Identical navigation semantics to + * Redesigned "glass" bottom tab bar. Identical navigation semantics to * CustomTabBar (route filtering, originalIndex/isFocused mapping, tabPress → * CommonActions.navigate) plus a sliding oval glass indicator that animates * from the previously active tab to the tapped one. diff --git a/constants/tabs.ts b/constants/tabs.ts index 7f9008965..5ed681a11 100644 --- a/constants/tabs.ts +++ b/constants/tabs.ts @@ -4,24 +4,24 @@ * The bottom tab bar is driven by two gates: the `href` on each `Tabs.Screen` * in `app/(protected)/(tabs)/_layout.tsx`, and the visible-name lists below * (consumed by the tab bar components). Keeping the lists here gives both the - * public bar (`CustomTabBar`) and the whitelisted bar (`NewCustomTabBar`) a + * legacy bar (`CustomTabBar`) and the redesigned bar (`NewCustomTabBar`) a * single source of truth. */ -/** Tabs shown to public (non-whitelisted) users — current behavior. */ +/** Tabs shown on the legacy bar (production) — current behavior. */ export const PUBLIC_TAB_NAMES = ['index', 'savings', 'card', 'activity'] as const; /** - * Tabs shown to whitelisted internal users on the redesigned bar. + * Tabs shown on the redesigned bar (qa/preview builds). * Card is merged into the wallet page and Activity moves to a header bell, so * neither appears here (their routes remain registered/navigable). */ export const WHITELIST_TAB_NAMES = ['index', 'savings', 'rewards'] as const; /** - * Per-route label overrides for the whitelisted bar. Lets us render "Wallet" + * Per-route label overrides for the redesigned bar. Lets us render "Wallet" * for the `index` route without changing the route's title in `_layout.tsx` - * (which would leak into the public bar and desktop nav). + * (which would leak into the legacy bar and desktop nav). */ export const WHITELIST_TAB_LABELS: Record = { index: 'Wallet', diff --git a/hooks/useDepositBuyCryptoOptions.tsx b/hooks/useDepositBuyCryptoOptions.tsx index 15639dbf1..2b5aae821 100644 --- a/hooks/useDepositBuyCryptoOptions.tsx +++ b/hooks/useDepositBuyCryptoOptions.tsx @@ -5,17 +5,16 @@ import { Image } from 'expo-image'; import { DEPOSIT_MODAL } from '@/constants/modals'; import { TRACKING_EVENTS } from '@/constants/tracking-events'; import { useCardStatus } from '@/hooks/useCardStatus'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; import { useOnrampAutomation } from '@/hooks/useOnrampAutomation'; import { track } from '@/lib/analytics'; import { getAsset } from '@/lib/assets'; +import { isDevFeatureEnabled } from '@/lib/config'; import { DepositMethod, RainApplicationStatus } from '@/lib/types'; import { useDepositStore } from '@/store/useDepositStore'; const useDepositBuyCryptoOptions = () => { const setModal = useDepositStore(state => state.setModal); const { data: cardStatus } = useCardStatus(); - const isTestUser = useIsTestUser(); const isRainApproved = cardStatus?.rainApplicationStatus === RainApplicationStatus.APPROVED; const { data: existingAutomation } = useOnrampAutomation(isRainApproved); @@ -56,8 +55,8 @@ const useDepositBuyCryptoOptions = () => { ); const filteredOptions = buyCryptoOptions - // Bank Deposit is gated behind the test-features allow list for now. - .filter(option => option.method !== 'bank_transfer' || isTestUser) + // Bank Deposit is in development: shown on qa/preview builds, hidden in production. + .filter(option => option.method !== 'bank_transfer' || isDevFeatureEnabled) .filter(option => Platform.OS !== 'ios' || option.method !== 'credit_card'); return { buyCryptoOptions: filteredOptions }; diff --git a/hooks/useIsTestUser.ts b/hooks/useIsTestUser.ts deleted file mode 100644 index c0593d129..000000000 --- a/hooks/useIsTestUser.ts +++ /dev/null @@ -1,7 +0,0 @@ -import useUser from '@/hooks/useUser'; -import { isUserAllowedToUseTestFeature } from '@/lib/utils/testFeatures'; - -export const useIsTestUser = (): boolean => { - const { user } = useUser(); - return isUserAllowedToUseTestFeature(user?.username ?? ''); -}; diff --git a/hooks/useNav.ts b/hooks/useNav.ts index fd975962b..8e5296267 100644 --- a/hooks/useNav.ts +++ b/hooks/useNav.ts @@ -1,7 +1,7 @@ import { Href } from 'expo-router'; import { path } from '@/constants/path'; -import { useIsTestUser } from '@/hooks/useIsTestUser'; +import { isDevFeatureEnabled } from '@/lib/config'; type MenuItem = { label: string; @@ -34,7 +34,6 @@ const stocks: MenuItem = { }; const useNav = () => { - const isTestUser = useIsTestUser(); const rewards: MenuItem = { label: 'Rewards', href: path.REWARDS, @@ -44,7 +43,7 @@ const useNav = () => { home, savings, card, - ...(isTestUser ? [stocks] : []), + ...(isDevFeatureEnabled ? [stocks] : []), rewards, activity, ]; diff --git a/lib/config.ts b/lib/config.ts index c55791a1c..4a5b513e5 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -73,6 +73,8 @@ export const EXPO_PUBLIC_PERSONA_SANDBOX_ENVIRONMENT_ID = process.env.EXPO_PUBLIC_PERSONA_SANDBOX_ENVIRONMENT_ID ?? ''; export const EXPO_PUBLIC_COINGECKO_API_KEY = process.env.EXPO_PUBLIC_COINGECKO_API_KEY ?? ''; export const isProduction = EXPO_PUBLIC_ENVIRONMENT === 'production'; +// In-development features: visible on qa/preview builds, hidden in production. +export const isDevFeatureEnabled = !isProduction; type Addresses = { ethereum: { diff --git a/lib/utils/index.ts b/lib/utils/index.ts index 438ff3912..ed1a1de39 100644 --- a/lib/utils/index.ts +++ b/lib/utils/index.ts @@ -1,6 +1,4 @@ export * from './activity'; export * from './multicall'; export * from './swap'; -export * from './testFeatures'; export * from './utils'; - diff --git a/lib/utils/testFeatures.ts b/lib/utils/testFeatures.ts deleted file mode 100644 index 2232a5a0e..000000000 --- a/lib/utils/testFeatures.ts +++ /dev/null @@ -1,22 +0,0 @@ -export const TEST_FEATURES_ALLOW_LIST = [ - 'Mark1', - 'mayank18', - 'mayankmittal', - 'smargon4', - 'LukaFuse', - 'Test', - 'InternSolid22', - 'mul53', - 'vigor-homey.2z', - 'maxxb.34980', - 'cimal67977', - 'vesas62360', - 'smargonaq1', -]; - -export const isUserAllowedToUseTestFeature = (username: string) => { - return ( - TEST_FEATURES_ALLOW_LIST.includes(username.toLowerCase()) || - TEST_FEATURES_ALLOW_LIST.includes(username) - ); -}; From 2d130b9cee1b2ad5de0576e99fed05a284e94e43 Mon Sep 17 00:00:00 2001 From: Mayank Mittal Date: Thu, 23 Jul 2026 00:16:10 +0530 Subject: [PATCH 2/5] fix: dev gating --- app/(protected)/(tabs)/_layout.tsx | 20 ++----------------- app/(protected)/(tabs)/card/details.tsx | 4 +--- app/(protected)/(tabs)/index.native.tsx | 4 +--- app/(protected)/(tabs)/index.tsx | 3 +-- app/(protected)/(tabs)/rewards/index.tsx | 3 +-- app/(protected)/(tabs)/savings.tsx | 4 ++-- app/(protected)/(tabs)/settings/index.tsx | 3 +-- .../AccountCenterDropdown.web.tsx | 3 +-- .../DepositToVault/VaultSelectorDropdown.tsx | 5 ++--- components/Navbar/NavbarMobile.tsx | 3 +-- components/Savings/SavingVault.tsx | 3 +-- components/Savings/SavingVaultOld.tsx | 3 +-- hooks/useDepositBuyCryptoOptions.tsx | 3 +-- hooks/useNav.ts | 10 +--------- 14 files changed, 17 insertions(+), 54 deletions(-) diff --git a/app/(protected)/(tabs)/_layout.tsx b/app/(protected)/(tabs)/_layout.tsx index c9d54a697..716e99b29 100644 --- a/app/(protected)/(tabs)/_layout.tsx +++ b/app/(protected)/(tabs)/_layout.tsx @@ -15,7 +15,6 @@ import RewardsTabIcon from '@/components/tabBar/RewardsTabIcon'; import TabBarBackground from '@/components/ui/TabBarBackground'; import { path } from '@/constants/path'; import { useDimension } from '@/hooks/useDimension'; -import { isDevFeatureEnabled } from '@/lib/config'; export default function TabLayout() { const { isDesktop } = useDimension(); @@ -50,12 +49,7 @@ export default function TabLayout() { position: 'absolute', }, }} - tabBar={ - !isDesktop - ? props => - isDevFeatureEnabled ? : - : undefined - } + tabBar={!isDesktop ? props => : undefined} backBehavior="history" > , // Only surface the Rewards tab (and its route) on qa/preview builds; // the redesigned NewCustomTabBar renders Wallet/Savings/Rewards. - href: isDevFeatureEnabled ? path.REWARDS : null, + href: null, }} /> - {isDevFeatureEnabled && ( - - )} state.active); @@ -239,7 +238,6 @@ export default function CardDetails() { shouldRevealDetails={shouldRevealDetails} onCardDetailsLoaded={handleCardDetailsLoaded} provider={provider} - useNewCard={devFeaturesEnabled} last4={cardLast4} /> ); diff --git a/app/(protected)/(tabs)/index.native.tsx b/app/(protected)/(tabs)/index.native.tsx index 8b2a71531..f737cdd1d 100644 --- a/app/(protected)/(tabs)/index.native.tsx +++ b/app/(protected)/(tabs)/index.native.tsx @@ -27,7 +27,6 @@ import { useTotalSavingsUSD } from '@/hooks/useTotalSavingsUSD'; import useUser from '@/hooks/useUser'; import { useVaultBalance } from '@/hooks/useVault'; import { useWalletTokens } from '@/hooks/useWalletTokens'; -import { isDevFeatureEnabled } from '@/lib/config'; import { useIntercom } from '@/lib/intercom'; import { SavingMode } from '@/lib/types'; import { formatBalanceUSD, hasCard } from '@/lib/utils'; @@ -199,6 +198,5 @@ function LegacyHome() { export default function Home() { // qa/preview builds see the redesigned wallet screen; production keeps the // existing design. Native is never desktop. - const showNewHome = isDevFeatureEnabled; - return showNewHome ? : ; + return ; } diff --git a/app/(protected)/(tabs)/index.tsx b/app/(protected)/(tabs)/index.tsx index 7d98fb804..9339d5399 100644 --- a/app/(protected)/(tabs)/index.tsx +++ b/app/(protected)/(tabs)/index.tsx @@ -30,7 +30,6 @@ import { useTotalSavingsUSD } from '@/hooks/useTotalSavingsUSD'; import useUser from '@/hooks/useUser'; import { useVaultBalance } from '@/hooks/useVault'; import { useWalletTokens } from '@/hooks/useWalletTokens'; -import { isDevFeatureEnabled } from '@/lib/config'; import { useIntercom } from '@/lib/intercom'; import { SavingMode } from '@/lib/types'; import { fontSize, formatBalanceUSD, hasCard } from '@/lib/utils'; @@ -264,6 +263,6 @@ export default function Home() { const { isDesktop } = useDimension(); // qa/preview builds on mobile-web see the redesigned wallet screen; desktop // web and production keep the existing design. - const showNewHome = isDevFeatureEnabled && !isDesktop; + const showNewHome = !isDesktop; return showNewHome ? : ; } diff --git a/app/(protected)/(tabs)/rewards/index.tsx b/app/(protected)/(tabs)/rewards/index.tsx index 5d6f50207..99e0b3f29 100644 --- a/app/(protected)/(tabs)/rewards/index.tsx +++ b/app/(protected)/(tabs)/rewards/index.tsx @@ -20,7 +20,6 @@ import { useCardStatus } from '@/hooks/useCardStatus'; import { useDimension } from '@/hooks/useDimension'; import { useOptInToRewards, useRewardsUserData } from '@/hooks/useRewards'; import { track } from '@/lib/analytics'; -import { isDevFeatureEnabled } from '@/lib/config'; import { hasCard } from '@/lib/utils'; import { useRewards } from '@/store/useRewardsStore'; import { useRewardsWelcomePopupStore } from '@/store/useRewardsWelcomePopupStore'; @@ -29,7 +28,7 @@ export default function Rewards() { // qa/preview builds see the redesigned rewards screen; production — and every // desktop-web user — keep the existing design. const { isDesktop } = useDimension(); - const showNew = isDevFeatureEnabled && !isDesktop; + const showNew = !isDesktop; return showNew ? : ; } diff --git a/app/(protected)/(tabs)/savings.tsx b/app/(protected)/(tabs)/savings.tsx index cbeb6191e..b10b16eac 100644 --- a/app/(protected)/(tabs)/savings.tsx +++ b/app/(protected)/(tabs)/savings.tsx @@ -36,7 +36,7 @@ import useUser from '@/hooks/useUser'; import { useTotalVaultBalance, useVaultBalance } from '@/hooks/useVault'; import { useVaultExchangeRate } from '@/hooks/useVaultExchangeRate'; import { getAsset } from '@/lib/assets'; -import { ADDRESSES, isDevFeatureEnabled } from '@/lib/config'; +import { ADDRESSES } from '@/lib/config'; import { SavingMode } from '@/lib/types'; import { fontSize, formatNumber } from '@/lib/utils'; import { useDepositStore } from '@/store/useDepositStore'; @@ -46,7 +46,7 @@ export default function Savings() { // qa/preview builds see the redesigned savings screen; production — and every // desktop-web user — keep the existing design. const { isDesktop } = useDimension(); - const showNew = isDevFeatureEnabled && !isDesktop; + const showNew = !isDesktop; return showNew ? : ; } diff --git a/app/(protected)/(tabs)/settings/index.tsx b/app/(protected)/(tabs)/settings/index.tsx index 4c7860002..23d37f584 100644 --- a/app/(protected)/(tabs)/settings/index.tsx +++ b/app/(protected)/(tabs)/settings/index.tsx @@ -27,7 +27,6 @@ import useNotificationPermissionStatus from '@/hooks/useNotificationPermissionSt import { useRewardsUserData } from '@/hooks/useRewards'; import useUser from '@/hooks/useUser'; import { getAsset } from '@/lib/assets'; -import { isDevFeatureEnabled } from '@/lib/config'; import { RewardsTier } from '@/lib/types'; import { cn, getUserDisplayName } from '@/lib/utils'; @@ -117,7 +116,7 @@ const MobileSettings = () => { const displayName = getUserDisplayName(user, 18); const [isReferralModalOpen, setIsReferralModalOpen] = useState(false); // GoodDollar is in development: shown only on qa/preview builds, hidden in production. - const canSeeGoodDollar = isDevFeatureEnabled; + const canSeeGoodDollar = false; const rowGroups: MobileSettingsRow[][] = [ [ diff --git a/components/AccountCenter/AccountCenterDropdown.web.tsx b/components/AccountCenter/AccountCenterDropdown.web.tsx index 0696ed296..e61f254c9 100644 --- a/components/AccountCenter/AccountCenterDropdown.web.tsx +++ b/components/AccountCenter/AccountCenterDropdown.web.tsx @@ -8,7 +8,6 @@ import { DropdownMenuTrigger, } from '@/components/ui/dropdown-menu'; import useUser from '@/hooks/useUser'; -import { isDevFeatureEnabled } from '@/lib/config'; import { cn } from '@/lib/utils'; import { @@ -31,7 +30,7 @@ const AccountCenterDropdown = () => { const insets = useSafeAreaInsets(); const { handleLogout } = useUser(); // GoodDollar is in development: shown only on qa/preview builds, hidden in production. - const canSeeGoodDollar = isDevFeatureEnabled; + const canSeeGoodDollar = false; const contentInsets = { top: insets.top, diff --git a/components/DepositToVault/VaultSelectorDropdown.tsx b/components/DepositToVault/VaultSelectorDropdown.tsx index 6de584aeb..f74344451 100644 --- a/components/DepositToVault/VaultSelectorDropdown.tsx +++ b/components/DepositToVault/VaultSelectorDropdown.tsx @@ -9,7 +9,6 @@ import { Text } from '@/components/ui/text'; import { VAULTS } from '@/constants/vaults'; import useVaultDepositConfig from '@/hooks/useVaultDepositConfig'; import { getAsset } from '@/lib/assets'; -import { isDevFeatureEnabled } from '@/lib/config'; import { Vault } from '@/lib/types'; import { getDefaultDepositSelection } from '@/lib/vaults'; import { useDepositStore } from '@/store/useDepositStore'; @@ -61,7 +60,7 @@ const VaultSelectorDropdown = () => { const handleSelect = (index: number) => { const vault = VAULTS[index]; - const isComingSoon = !!vault?.isComingSoon && !isDevFeatureEnabled; + const isComingSoon = !!vault?.isComingSoon; if (isComingSoon || !vault) return; selectVaultForDeposit(index); @@ -136,7 +135,7 @@ const VaultSelectorDropdown = () => { {VAULTS.map((vault, index) => { const isSelected = vault.name === selectedVault.name; - const isComingSoon = !!vault.isComingSoon && !isDevFeatureEnabled; + const isComingSoon = !!vault.isComingSoon; return ( { const { isScreenMedium } = useDimension(); const vaultIndex = VAULTS.findIndex(v => v.name === vault.name); const isSelected = selectedVault === vaultIndex; - const isComingSoon = !!vault.isComingSoon && !isDevFeatureEnabled; + const isComingSoon = !!vault.isComingSoon; const gapHeight = isScreenMedium ? 12 : 0; const iconSizeSelected = isScreenMedium ? 53 : 28; diff --git a/components/Savings/SavingVaultOld.tsx b/components/Savings/SavingVaultOld.tsx index cab009430..33e3e4adc 100644 --- a/components/Savings/SavingVaultOld.tsx +++ b/components/Savings/SavingVaultOld.tsx @@ -19,7 +19,6 @@ import { useMaxAPY } from '@/hooks/useAnalytics'; import { useDimension } from '@/hooks/useDimension'; import { useVaultTotalValueOld } from '@/hooks/useVaultTotalValueOld'; import { getAsset } from '@/lib/assets'; -import { isDevFeatureEnabled } from '@/lib/config'; import { Vault } from '@/lib/types'; import { compactNumberFormat } from '@/lib/utils'; import { useSavingStore } from '@/store/useSavingStore'; @@ -48,7 +47,7 @@ const SavingVaultOld = ({ vault }: SavingVaultOldProps) => { const { isScreenMedium } = useDimension(); const vaultIndex = VAULTS.findIndex(v => v.name === vault.name); const isSelected = selectedVault === vaultIndex; - const isComingSoon = !!vault.isComingSoon && !isDevFeatureEnabled; + const isComingSoon = !!vault.isComingSoon; const gapHeight = isScreenMedium ? 12 : 0; const iconSizeSelected = isScreenMedium ? 53 : 28; diff --git a/hooks/useDepositBuyCryptoOptions.tsx b/hooks/useDepositBuyCryptoOptions.tsx index 2b5aae821..5bc157703 100644 --- a/hooks/useDepositBuyCryptoOptions.tsx +++ b/hooks/useDepositBuyCryptoOptions.tsx @@ -8,7 +8,6 @@ import { useCardStatus } from '@/hooks/useCardStatus'; import { useOnrampAutomation } from '@/hooks/useOnrampAutomation'; import { track } from '@/lib/analytics'; import { getAsset } from '@/lib/assets'; -import { isDevFeatureEnabled } from '@/lib/config'; import { DepositMethod, RainApplicationStatus } from '@/lib/types'; import { useDepositStore } from '@/store/useDepositStore'; @@ -56,7 +55,7 @@ const useDepositBuyCryptoOptions = () => { const filteredOptions = buyCryptoOptions // Bank Deposit is in development: shown on qa/preview builds, hidden in production. - .filter(option => option.method !== 'bank_transfer' || isDevFeatureEnabled) + .filter(option => option.method !== 'bank_transfer') .filter(option => Platform.OS !== 'ios' || option.method !== 'credit_card'); return { buyCryptoOptions: filteredOptions }; diff --git a/hooks/useNav.ts b/hooks/useNav.ts index 8e5296267..6992ca778 100644 --- a/hooks/useNav.ts +++ b/hooks/useNav.ts @@ -1,7 +1,6 @@ import { Href } from 'expo-router'; import { path } from '@/constants/path'; -import { isDevFeatureEnabled } from '@/lib/config'; type MenuItem = { label: string; @@ -39,14 +38,7 @@ const useNav = () => { href: path.REWARDS, }; // Agent lives in the account-center menu, not the navbar. - const menuItems: MenuItem[] = [ - home, - savings, - card, - ...(isDevFeatureEnabled ? [stocks] : []), - rewards, - activity, - ]; + const menuItems: MenuItem[] = [home, savings, card, rewards, activity]; return { menuItems }; }; From 021832c322ab342e539b617da9e9ce00ce7a0afd Mon Sep 17 00:00:00 2001 From: Mayank Mittal Date: Thu, 23 Jul 2026 00:18:30 +0530 Subject: [PATCH 3/5] fix: dev gating --- app/(protected)/(tabs)/card/details.tsx | 32 ++++--------------------- 1 file changed, 4 insertions(+), 28 deletions(-) diff --git a/app/(protected)/(tabs)/card/details.tsx b/app/(protected)/(tabs)/card/details.tsx index cd1feeb46..95f82e374 100644 --- a/app/(protected)/(tabs)/card/details.tsx +++ b/app/(protected)/(tabs)/card/details.tsx @@ -247,36 +247,13 @@ export default function CardDetails() { // card must be laid out right away so the hero transition can measure its // destination and land smoothly. Data fills in as it arrives (balance/last-4 // are usually already warm from the home screen's query). - + {/* The redesigned screen drops the "Card" heading — the card image is the top section; production/desktop keep the heading. */} - {!devFeaturesEnabled && pageHeader} - - {!devFeaturesEnabled && } - {devFeaturesEnabled ? ( - // Card is the top section, full-bleed (cancel the container's px-4) to - // match the home card width. The Show details button peeks out from - // behind it (card sits above via z-10). - - {/* pointerEvents none: the card sits above the button (z-10) and - its bounds include the transparent bottom-shadow region that - overlaps the button — without this it would swallow the button's - taps. The card itself isn't interactive on this screen. */} - - {cardImageSection} - - - ) : ( - cardImageSection - )} + + + {cardImageSection} From 4080b808a59c1b15331ad63c5aac30adf432784a Mon Sep 17 00:00:00 2001 From: Mayank Mittal Date: Thu, 23 Jul 2026 00:19:56 +0530 Subject: [PATCH 4/5] fix: dev gating --- app/(protected)/(tabs)/card/details.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/(protected)/(tabs)/card/details.tsx b/app/(protected)/(tabs)/card/details.tsx index 95f82e374..9bf8a49cd 100644 --- a/app/(protected)/(tabs)/card/details.tsx +++ b/app/(protected)/(tabs)/card/details.tsx @@ -250,10 +250,10 @@ export default function CardDetails() { {/* The redesigned screen drops the "Card" heading — the card image is the top section; production/desktop keep the heading. */} + {pageHeader} - {cardImageSection} Date: Thu, 23 Jul 2026 00:25:44 +0530 Subject: [PATCH 5/5] fix: dev gating --- app/(protected)/(tabs)/_layout.tsx | 3 +-- app/(protected)/(tabs)/index.native.tsx | 3 +-- app/(protected)/(tabs)/index.tsx | 6 +----- app/(protected)/(tabs)/rewards/index.tsx | 6 +----- app/(protected)/(tabs)/savings.tsx | 6 +----- components/Navbar/NavbarMobile.tsx | 20 +++++++------------- 6 files changed, 12 insertions(+), 32 deletions(-) diff --git a/app/(protected)/(tabs)/_layout.tsx b/app/(protected)/(tabs)/_layout.tsx index 716e99b29..1f9090b2d 100644 --- a/app/(protected)/(tabs)/_layout.tsx +++ b/app/(protected)/(tabs)/_layout.tsx @@ -10,7 +10,6 @@ import lightningAnimation from '@/assets/tabs-icons/lightning.json'; import { CustomTabBar } from '@/components/CustomTabBar'; import { HapticTab } from '@/components/HapticTab'; import { LottieTabIcon } from '@/components/LottieTabIcon'; -import { NewCustomTabBar } from '@/components/tabBar/NewCustomTabBar'; import RewardsTabIcon from '@/components/tabBar/RewardsTabIcon'; import TabBarBackground from '@/components/ui/TabBarBackground'; import { path } from '@/constants/path'; @@ -49,7 +48,7 @@ export default function TabLayout() { position: 'absolute', }, }} - tabBar={!isDesktop ? props => : undefined} + tabBar={!isDesktop ? props => : undefined} backBehavior="history" > ; + return ; } diff --git a/app/(protected)/(tabs)/index.tsx b/app/(protected)/(tabs)/index.tsx index 9339d5399..6a13c1829 100644 --- a/app/(protected)/(tabs)/index.tsx +++ b/app/(protected)/(tabs)/index.tsx @@ -260,9 +260,5 @@ function LegacyHome() { } export default function Home() { - const { isDesktop } = useDimension(); - // qa/preview builds on mobile-web see the redesigned wallet screen; desktop - // web and production keep the existing design. - const showNewHome = !isDesktop; - return showNewHome ? : ; + return ; } diff --git a/app/(protected)/(tabs)/rewards/index.tsx b/app/(protected)/(tabs)/rewards/index.tsx index 99e0b3f29..b68cc008f 100644 --- a/app/(protected)/(tabs)/rewards/index.tsx +++ b/app/(protected)/(tabs)/rewards/index.tsx @@ -25,11 +25,7 @@ import { useRewards } from '@/store/useRewardsStore'; import { useRewardsWelcomePopupStore } from '@/store/useRewardsWelcomePopupStore'; export default function Rewards() { - // qa/preview builds see the redesigned rewards screen; production — and every - // desktop-web user — keep the existing design. - const { isDesktop } = useDimension(); - const showNew = !isDesktop; - return showNew ? : ; + return ; } function LegacyRewards() { diff --git a/app/(protected)/(tabs)/savings.tsx b/app/(protected)/(tabs)/savings.tsx index b10b16eac..7e1ab6fa9 100644 --- a/app/(protected)/(tabs)/savings.tsx +++ b/app/(protected)/(tabs)/savings.tsx @@ -43,11 +43,7 @@ import { useDepositStore } from '@/store/useDepositStore'; import { useSavingStore } from '@/store/useSavingStore'; export default function Savings() { - // qa/preview builds see the redesigned savings screen; production — and every - // desktop-web user — keep the existing design. - const { isDesktop } = useDimension(); - const showNew = !isDesktop; - return showNew ? : ; + return ; } function LegacySavings() { diff --git a/components/Navbar/NavbarMobile.tsx b/components/Navbar/NavbarMobile.tsx index 5472c3a6a..ec1676362 100644 --- a/components/Navbar/NavbarMobile.tsx +++ b/components/Navbar/NavbarMobile.tsx @@ -14,8 +14,6 @@ import { Text } from '@/components/ui/text'; import useUser from '@/hooks/useUser'; import { getAsset } from '@/lib/assets'; -import HeaderBellButton from './HeaderBellButton'; -import HeaderProfileButton from './HeaderProfileButton'; import RegisterButtons from './RegisterButtons'; import WhatsNewButton from './WhatsNewButton'; @@ -113,16 +111,12 @@ const NavbarMobile = ({ )} - {showNewHeader ? ( - - ) : ( - Solid logo - )} + Solid logo {!!title && ( - {showNewHeader ? : } + ) : (