diff --git a/codecov.yml b/codecov.yml index db921b0b00..c865e13f93 100644 --- a/codecov.yml +++ b/codecov.yml @@ -9,6 +9,7 @@ ignore: - "**/styled.tsx" - "**/constants/**/*" - "constants/**/*" + - "src/dev/*" coverage: status: diff --git a/src/components/TopLevelModals/index.tsx b/src/components/TopLevelModals/index.tsx index daf41444a8..44bddf3813 100644 --- a/src/components/TopLevelModals/index.tsx +++ b/src/components/TopLevelModals/index.tsx @@ -6,11 +6,13 @@ import BaseAnnouncementBanner from 'components/Banner/BaseAnnouncementBanner' import AddressClaimModal from 'components/claim/AddressClaimModal' import ConnectedAccountBlocked from 'components/ConnectedAccountBlocked' import FiatOnrampModal from 'components/FiatOnrampModal' +import DevFlagsBox from 'dev/DevFlagsBox' import useAccountRiskCheck from 'hooks/useAccountRiskCheck' import Bag from 'nft/components/bag/Bag' import TransactionCompleteModal from 'nft/components/collection/TransactionCompleteModal' import { useModalIsOpen, useToggleModal } from 'state/application/hooks' import { ApplicationModal } from 'state/application/reducer' +import { isDevelopmentEnv, isStagingEnv } from 'utils/env' export default function TopLevelModals() { const addressClaimOpen = useModalIsOpen(ApplicationModal.ADDRESS_CLAIM) @@ -19,6 +21,7 @@ export default function TopLevelModals() { const { account } = useWeb3React() useAccountRiskCheck(account) const accountBlocked = Boolean(blockedAccountModalOpen && account) + const shouldShowDevFlags = isDevelopmentEnv() || isStagingEnv() return ( <> @@ -31,6 +34,7 @@ export default function TopLevelModals() { + {shouldShowDevFlags && } ) } diff --git a/src/dev/DevFlagsBox.tsx b/src/dev/DevFlagsBox.tsx new file mode 100644 index 0000000000..f8d60abbac --- /dev/null +++ b/src/dev/DevFlagsBox.tsx @@ -0,0 +1,67 @@ +import { BaseVariant, FeatureFlag, featureFlagSettings as featureFlagSettingsAtom } from 'featureFlags' +import { useAtomValue } from 'jotai/utils' +import { useMemo, useState } from 'react' +import { useGate } from 'statsig-react' +import styled from 'styled-components' +import { ThemedText } from 'theme/components' +import { isDevelopmentEnv, isStagingEnv } from 'utils/env' + +const Box = styled.div` + position: fixed; + bottom: 20px; + left: 20px; + background-color: ${({ theme }) => theme.surface1}; + padding: 10px; + border: 1px solid ${({ theme }) => theme.accent1}; + z-index: 1000; + + @media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.md}px`}) { + bottom: 70px; + } +` +const TopBar = styled.div` + display: flex; + justify-content: space-between; +` +const Gate = (flagName: string, featureFlagSettings: Record) => { + const gateResult = useGate(flagName) + if (gateResult) { + const { value: statsigValue }: { value: boolean } = gateResult + const flagSetting = featureFlagSettings[flagName] + const settingValue: boolean = flagSetting === BaseVariant.Enabled + if (flagSetting && statsigValue !== settingValue) { + return ( + + {flagName}: {flagSetting} + + ) + } + } + return null +} + +export default function DevFlagsBox() { + const featureFlagsAtom = useAtomValue(featureFlagSettingsAtom) + const featureFlags = useMemo(() => Object.values(FeatureFlag), []) + + const overrides = featureFlags.map((flagName) => Gate(flagName, featureFlagsAtom)) + const hasOverrides = overrides.some((g) => g !== null) + + const [isOpen, setIsOpen] = useState(true) + const toggleOpen = () => setIsOpen((open) => !open) + + return ( + + + {isOpen ? 'πŸ˜ΊπŸ‘‡' : '😿☝️'} + {isOpen && ( + + {isStagingEnv() && 'Staging build overrides'} + {isDevelopmentEnv() && 'Development build overrides'} + + )} + + {isOpen && (hasOverrides ? overrides : No overrides)} + + ) +}