Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mchx campaign banner and mint on gallery #2423

Merged
merged 6 commits into from
Apr 12, 2024
Merged
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
100 changes: 100 additions & 0 deletions apps/mobile/src/components/ClaimMintUpsellBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { useCallback } from 'react';
import { View } from 'react-native';
import { graphql, useFragment } from 'react-relay';
import { MCHX_CLAIM_CODE_KEY } from 'src/constants/storageKeys';
import usePersistedState from 'src/hooks/usePersistedState';
import { XMarkIcon } from 'src/icons/XMarkIcon';

import { useBottomSheetModalActions } from '~/contexts/BottomSheetModalContext';
import { ClaimMintUpsellBannerFragment$key } from '~/generated/ClaimMintUpsellBannerFragment.graphql';
import { contexts } from '~/shared/analytics/constants';
import colors from '~/shared/theme/colors';

import { Button } from './Button';
import { GalleryTouchableOpacity } from './GalleryTouchableOpacity';
import MintCampaignBottomSheet from './Mint/MintCampaign/MintCampaignBottomSheet';
import { Typography } from './Typography';

type Props = {
queryRef: ClaimMintUpsellBannerFragment$key;
};

export function ClaimMintUpsellBanner({ queryRef }: Props) {
const query = useFragment(
graphql`
fragment ClaimMintUpsellBannerFragment on Query {
viewer {
... on Viewer {
user {
__typename
}
}
}
}
`,
queryRef
);

const { showBottomSheetModal, hideBottomSheetModal } = useBottomSheetModalActions();

const [claimCode] = usePersistedState(MCHX_CLAIM_CODE_KEY, '');

const [isUpsellMintBannerDismissed, setIsUpsellMintBannerDismissed] = usePersistedState(
'isUpsellMintBannerDismissed',
false
);

const handleDismissUpsellBanner = useCallback(() => {
setIsUpsellMintBannerDismissed(true);
}, [setIsUpsellMintBannerDismissed]);

const handleClaimPress = useCallback(() => {
showBottomSheetModal({ content: <MintCampaignBottomSheet onClose={hideBottomSheetModal} /> });
}, [hideBottomSheetModal, showBottomSheetModal]);

const user = query.viewer?.user;

if (!user || claimCode || isUpsellMintBannerDismissed) {
return <View className="bg-white dark:bg-black-900" />;
}

return (
<View className="bg-activeBlue dark:bg-darkModeBlue w-full px-4 py-2 flex-row items-center justify-between">
<View>
<Typography
font={{ family: 'ABCDiatype', weight: 'Bold' }}
className="text-offWhite text-sm"
>
Exclusive free mint
</Typography>
<Typography
font={{ family: 'ABCDiatype', weight: 'Regular' }}
className="text-offWhite text-xs"
>
Claim your free generative work by MCHX
</Typography>
</View>
<View className="flex-row items-center space-x-2">
<Button
onPress={handleClaimPress}
text="claim"
size="xs"
variant="secondary"
fontWeight="Bold"
eventElementId="Press Claim Upsell Banner"
eventName="Press Claim Upsell Banner"
eventContext={contexts.Authentication}
/>
<GalleryTouchableOpacity
className="p-2"
eventElementId="Close Claim Upsell Banner"
eventName="Close Claim Upsell Banner"
eventContext={contexts.Authentication}
onPress={handleDismissUpsellBanner}
>
<XMarkIcon color={colors.offWhite} />
</GalleryTouchableOpacity>
</View>
</View>
);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { View } from 'react-native';
import { graphql, useFragment } from 'react-relay';
import { extractRelevantMetadataFromToken } from 'shared/utils/extractRelevantMetadataFromToken';
import { isRadianceContractAddress } from 'src/utils/isRadianceContractAddress';

import { MintLinkButton } from '~/components/MintLinkButton';
import { PostListMintButtonSectionFragment$key } from '~/generated/PostListMintButtonSectionFragment.graphql';
Expand All @@ -15,6 +17,7 @@ export function PostListMintButtonSection({ postRef }: Props) {
fragment PostListMintButtonSectionFragment on Post {
tokens {
...MintLinkButtonFragment
...extractRelevantMetadataFromTokenFragment
}
author {
primaryWallet {
Expand All @@ -31,13 +34,21 @@ export function PostListMintButtonSection({ postRef }: Props) {

const token = post?.tokens?.[0];

if (!token) {
throw new Error('no token exists for thist post');
}

const ownerWalletAddress = post?.author?.primaryWallet?.chainAddress?.address ?? '';

const userAddedMintURL = post?.userAddedMintURL ?? '';

const { contractAddress } = extractRelevantMetadataFromToken(token);

const isRadiance = isRadianceContractAddress(contractAddress);

return (
<View className="px-3 pb-8 pt-2">
{token && userAddedMintURL && (
{(isRadiance || userAddedMintURL) && token && (
<MintLinkButton
tokenRef={token}
variant="secondary"
Expand Down
39 changes: 31 additions & 8 deletions apps/mobile/src/components/MintLinkButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,20 @@ import { useColorScheme } from 'nativewind';
import { useCallback, useMemo } from 'react';
import { Linking, ViewStyle } from 'react-native';
import { graphql, useFragment } from 'react-relay';
import { MCHX_CLAIM_CODE_KEY } from 'src/constants/storageKeys';
import usePersistedState from 'src/hooks/usePersistedState';
import { EnsembleIcon } from 'src/icons/EnsembleIcon';
import { FoundationIcon } from 'src/icons/FoundationIcon';
import { FxHashIcon } from 'src/icons/FxHashIcon';
import { GLogoIcon } from 'src/icons/GLogoIcon';
import { HighlightIcon } from 'src/icons/HighlightIcon';
import { ProhibitionIcon } from 'src/icons/ProhibitionIcon';
import { SuperRareIcon } from 'src/icons/SuperRareIcon';
import { TopRightArrowIcon } from 'src/icons/TopRightArrowIcon';
import { ZoraIcon } from 'src/icons/ZoraIcon';
import { isRadianceContractAddress } from 'src/utils/isRadianceContractAddress';

import { useBottomSheetModalActions } from '~/contexts/BottomSheetModalContext';
import { MintLinkButtonFragment$key } from '~/generated/MintLinkButtonFragment.graphql';
import { GalleryElementTrackingProps } from '~/shared/contexts/AnalyticsContext';
import colors from '~/shared/theme/colors';
Expand All @@ -23,6 +28,7 @@ import {
} from '~/shared/utils/getMintUrlWithReferrer';

import { Button, ButtonProps } from './Button';
import MintCampaignBottomSheet from './Mint/MintCampaign/MintCampaignBottomSheet';

type Props = {
// in order to generate the mint URL with the correct params, we either grab it
Expand Down Expand Up @@ -78,11 +84,17 @@ export function MintLinkButton({
};
}, [overrideMetadata, token]);

const isRadiance = isRadianceContractAddress(contractAddress);

const { url: mintURL, provider: mintProviderType } = getMintUrlWithReferrer(
overrideMintUrl || mintUrl,
referrerAddress ?? ''
);

const { showBottomSheetModal, hideBottomSheetModal } = useBottomSheetModalActions();

const [claimCode] = usePersistedState(MCHX_CLAIM_CODE_KEY, '');

const mintProvider: {
buttonText: string;
icon: React.ReactNode;
Expand Down Expand Up @@ -113,10 +125,17 @@ export function MintLinkButton({
icon: <SuperRareIcon width={size === 'sm' ? 16 : 24} height={size === 'sm' ? 16 : 24} />,
};
} else if (mintProviderType === 'Highlight') {
return {
buttonText: 'mint on highlight',
icon: <HighlightIcon width={size === 'sm' ? 16 : 24} height={size === 'sm' ? 16 : 24} />,
};
if (isRadiance && !claimCode) {
return {
buttonText: 'mint on gallery',
icon: <GLogoIcon width={16} height={16} invertColor={variant === 'primary'} />,
};
} else {
return {
buttonText: 'mint on highlight',
icon: <HighlightIcon width={size === 'sm' ? 16 : 24} height={size === 'sm' ? 16 : 24} />,
};
}
} else if (mintProviderType === 'Foundation') {
return {
buttonText: 'mint on foundation',
Expand All @@ -125,11 +144,15 @@ export function MintLinkButton({
} else {
return null;
}
}, [mintProviderType, size]);
}, [claimCode, isRadiance, mintProviderType, size, variant]);

const handlePress = useCallback(() => {
Linking.openURL(mintURL);
}, [mintURL]);
if (isRadiance) {
showBottomSheetModal({ content: <MintCampaignBottomSheet onClose={hideBottomSheetModal} /> });
} else {
Linking.openURL(mintURL);
}
}, [hideBottomSheetModal, isRadiance, mintURL, showBottomSheetModal]);

const arrowColor = useMemo(() => {
const colorMap = {
Expand Down Expand Up @@ -164,7 +187,7 @@ export function MintLinkButton({
variant={variant}
onPress={handlePress}
headerElement={mintProvider.icon}
footerElement={<TopRightArrowIcon color={arrowColor} />}
footerElement={isRadiance && !claimCode ? null : <TopRightArrowIcon color={arrowColor} />}
style={style}
size={size}
eventElementId="Mint Link Button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,13 @@ export function NotificationSkeleton({
[notification.followers?.edges, notification.user]
);

// TODO Get data from sanity
const isPinned = false;

return (
<GalleryTouchableOpacity
onPress={onPress}
className="flex flex-row justify-between p-4"
className={`flex flex-row justify-between p-4 ${isPinned && 'm-4 border border-blue-700'}`}
eventElementId="Notification Row"
eventName="Notification Row Clicked"
eventContext={contexts.Notifications}
Expand Down
16 changes: 14 additions & 2 deletions apps/mobile/src/icons/GLogoIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,34 @@ import colors from '~/shared/theme/colors';
type Props = {
height?: number;
width?: number;
invertColor?: boolean;
};

const originalWidth = 25;
const originalHeight = 33;

export function GLogoIcon({ width = originalWidth, height = originalHeight }: Props) {
export function GLogoIcon({
width = originalWidth,
height = originalHeight,
invertColor = false,
}: Props) {
const { colorScheme } = useColorScheme();

const scaledWidth = (height * originalWidth) / originalHeight;
const scaledHeight = (width * originalHeight) / originalWidth;

const fill = React.useMemo(() => {
if (invertColor) {
return colorScheme === 'dark' ? colors.black['800'] : colors.white;
}
return colorScheme === 'dark' ? colors.white : colors.black['800'];
}, [colorScheme, invertColor]);

return (
<Svg width={scaledWidth} height={scaledHeight} viewBox="0 0 25 33" fill="none">
<Path
d="M22.2 20.672c0-2.976.452-3.743 2.21-3.878v-1.622H11.787v1.622c4.282.181 6.539-.327 6.539 3.385l.013 5.924a7.662 7.662 0 01-.956 2.11c-.926 1.353-2.46 1.983-4.531 1.983-4.909 0-7.813-5.183-7.813-14.108S7.715 1.853 13.077 1.853c4.147 0 6.643 2.739 7.278 8.507h1.848V.574h-1.758c-.225 1.127-.407 1.442-.813 1.442-.719 0-2.721-2.016-6.731-2.016C5.376 0 .416 6.748.416 16.257c0 9.599 4.74 15.818 12.526 15.818h.015c4.592 0 6.058-3.064 6.369-4.04l1.102 3.635h1.758l.014-10.998z"
fill={colorScheme === 'dark' ? colors.white : colors.black['800']}
fill={fill}
/>
</Svg>
);
Expand Down
3 changes: 3 additions & 0 deletions apps/mobile/src/navigation/RootStackNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { View } from 'react-native';
import { graphql, useFragment, useLazyLoadQuery } from 'react-relay';
import { useMaintenanceContext } from 'shared/contexts/MaintenanceStatusContext';

import { ClaimMintUpsellBanner } from '~/components/ClaimMintUpsellBanner';
import { ConnectWalletUpsellBanner } from '~/components/ConnectWalletUpsellBanner';
import { MaintenanceNoticeBottomSheetWrapper } from '~/components/MaintenanceScreen';
import { RootStackNavigatorFragment$key } from '~/generated/RootStackNavigatorFragment.graphql';
Expand Down Expand Up @@ -116,6 +117,7 @@ function MainScreen({ queryRef }: MainScreenProps) {
graphql`
fragment RootStackNavigatorFragment on Query {
...ConnectWalletUpsellBannerFragment
...ClaimMintUpsellBannerFragment
}
`,
queryRef
Expand All @@ -125,6 +127,7 @@ function MainScreen({ queryRef }: MainScreenProps) {
<View className="flex-1">
<Suspense fallback={<View />}>
<ConnectWalletUpsellBanner queryRef={query} />
<ClaimMintUpsellBanner queryRef={query} />
</Suspense>
<MainTabNavigator />
</View>
Expand Down
5 changes: 5 additions & 0 deletions apps/mobile/src/utils/isRadianceContractAddress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const RADIANCE_CONTRACT_ADDRESS = '0x78b92e9afd56b033ead2103f07aced5fac8c0854';

export const isRadianceContractAddress = (contractAddress: string): boolean => {
return contractAddress === RADIANCE_CONTRACT_ADDRESS;
};
1 change: 1 addition & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -2835,6 +2835,7 @@ enum UserExperienceType {
PostsBetaAnnouncement
CreatorBetaFullscreenAnnouncementModal
CreatorBetaMicroAnnouncementModal
RadianceMintApr2024
}

type UserFollowedUsersFeedEventData implements FeedEventData {
Expand Down
Loading