diff --git a/apps/mobile/src/components/ClaimMintUpsellBanner.tsx b/apps/mobile/src/components/ClaimMintUpsellBanner.tsx
new file mode 100644
index 0000000000..94ce20c97b
--- /dev/null
+++ b/apps/mobile/src/components/ClaimMintUpsellBanner.tsx
@@ -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: });
+ }, [hideBottomSheetModal, showBottomSheetModal]);
+
+ const user = query.viewer?.user;
+
+ if (!user || claimCode || isUpsellMintBannerDismissed) {
+ return ;
+ }
+
+ return (
+
+
+
+ Exclusive free mint
+
+
+ Claim your free generative work by MCHX
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/apps/mobile/src/components/Feed/Posts/PostListMintButtonSection.tsx b/apps/mobile/src/components/Feed/Posts/PostListMintButtonSection.tsx
index 17b326ce4f..dc08614333 100644
--- a/apps/mobile/src/components/Feed/Posts/PostListMintButtonSection.tsx
+++ b/apps/mobile/src/components/Feed/Posts/PostListMintButtonSection.tsx
@@ -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';
@@ -15,6 +17,7 @@ export function PostListMintButtonSection({ postRef }: Props) {
fragment PostListMintButtonSectionFragment on Post {
tokens {
...MintLinkButtonFragment
+ ...extractRelevantMetadataFromTokenFragment
}
author {
primaryWallet {
@@ -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 (
- {token && userAddedMintURL && (
+ {(isRadiance || userAddedMintURL) && token && (
,
};
} else if (mintProviderType === 'Highlight') {
- return {
- buttonText: 'mint on highlight',
- icon: ,
- };
+ if (isRadiance && !claimCode) {
+ return {
+ buttonText: 'mint on gallery',
+ icon: ,
+ };
+ } else {
+ return {
+ buttonText: 'mint on highlight',
+ icon: ,
+ };
+ }
} else if (mintProviderType === 'Foundation') {
return {
buttonText: 'mint on foundation',
@@ -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: });
+ } else {
+ Linking.openURL(mintURL);
+ }
+ }, [hideBottomSheetModal, isRadiance, mintURL, showBottomSheetModal]);
const arrowColor = useMemo(() => {
const colorMap = {
@@ -164,7 +187,7 @@ export function MintLinkButton({
variant={variant}
onPress={handlePress}
headerElement={mintProvider.icon}
- footerElement={}
+ footerElement={isRadiance && !claimCode ? null : }
style={style}
size={size}
eventElementId="Mint Link Button"
diff --git a/apps/mobile/src/components/Notification/NotificationSkeleton.tsx b/apps/mobile/src/components/Notification/NotificationSkeleton.tsx
index d7d52e05d5..945a663618 100644
--- a/apps/mobile/src/components/Notification/NotificationSkeleton.tsx
+++ b/apps/mobile/src/components/Notification/NotificationSkeleton.tsx
@@ -258,10 +258,13 @@ export function NotificationSkeleton({
[notification.followers?.edges, notification.user]
);
+ // TODO Get data from sanity
+ const isPinned = false;
+
return (
{
+ if (invertColor) {
+ return colorScheme === 'dark' ? colors.black['800'] : colors.white;
+ }
+ return colorScheme === 'dark' ? colors.white : colors.black['800'];
+ }, [colorScheme, invertColor]);
+
return (
);
diff --git a/apps/mobile/src/navigation/RootStackNavigator.tsx b/apps/mobile/src/navigation/RootStackNavigator.tsx
index 5c6ba5030f..3dc5f8da61 100644
--- a/apps/mobile/src/navigation/RootStackNavigator.tsx
+++ b/apps/mobile/src/navigation/RootStackNavigator.tsx
@@ -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';
@@ -116,6 +117,7 @@ function MainScreen({ queryRef }: MainScreenProps) {
graphql`
fragment RootStackNavigatorFragment on Query {
...ConnectWalletUpsellBannerFragment
+ ...ClaimMintUpsellBannerFragment
}
`,
queryRef
@@ -125,6 +127,7 @@ function MainScreen({ queryRef }: MainScreenProps) {
}>
+
diff --git a/apps/mobile/src/utils/isRadianceContractAddress.ts b/apps/mobile/src/utils/isRadianceContractAddress.ts
new file mode 100644
index 0000000000..b569655ed2
--- /dev/null
+++ b/apps/mobile/src/utils/isRadianceContractAddress.ts
@@ -0,0 +1,5 @@
+const RADIANCE_CONTRACT_ADDRESS = '0x78b92e9afd56b033ead2103f07aced5fac8c0854';
+
+export const isRadianceContractAddress = (contractAddress: string): boolean => {
+ return contractAddress === RADIANCE_CONTRACT_ADDRESS;
+};
diff --git a/schema.graphql b/schema.graphql
index 1cd41b8f52..0130bea5f7 100644
--- a/schema.graphql
+++ b/schema.graphql
@@ -2835,6 +2835,7 @@ enum UserExperienceType {
PostsBetaAnnouncement
CreatorBetaFullscreenAnnouncementModal
CreatorBetaMicroAnnouncementModal
+ RadianceMintApr2024
}
type UserFollowedUsersFeedEventData implements FeedEventData {