diff --git a/apps/mobile/src/App.tsx b/apps/mobile/src/App.tsx index fb73279fb3..6df52aa8be 100644 --- a/apps/mobile/src/App.tsx +++ b/apps/mobile/src/App.tsx @@ -37,6 +37,7 @@ import ToastProvider from './contexts/ToastContext'; import { TokenStateManagerProvider } from './contexts/TokenStateManagerContext'; import { magic } from './magic'; import { useCacheIntroVideo } from './screens/Onboarding/useCacheIntroVideo'; +import SanityDataProvider from './contexts/SanityDataContext'; SplashScreen.preventAutoHideAsync(); @@ -157,28 +158,30 @@ export default function App() { - - - - - - - - {/* Register the user's push token if one exists (does not prompt the user) */} - - - - - - - - - - - - + + + + + + + + + {/* Register the user's push token if one exists (does not prompt the user) */} + + + + + + + + + + + + + diff --git a/apps/mobile/src/components/Mint/MintCampaign/MintCampaignBottomSheet.tsx b/apps/mobile/src/components/Mint/MintCampaign/MintCampaignBottomSheet.tsx index 728d020efc..5c52b6f9b4 100644 --- a/apps/mobile/src/components/Mint/MintCampaign/MintCampaignBottomSheet.tsx +++ b/apps/mobile/src/components/Mint/MintCampaign/MintCampaignBottomSheet.tsx @@ -1,18 +1,48 @@ -import { MCHX_CLAIM_CODE_KEY } from 'src/constants/storageKeys'; +import { useMemo } from 'react'; import usePersistedState from 'src/hooks/usePersistedState'; +import { useSanityDataContext } from '~/contexts/SanityDataContext'; + import MintCampaignPostTransaction from './MintCampaignPostTransaction'; import MintCampaignPreTransaction from './MintCampaignPreTransaction'; -export default function MintCampaignBottomSheet({ onClose }: { onClose: () => void }) { +type Props = { + onClose?: () => void; + projectInternalId?: string; +}; + +export default function MintCampaignBottomSheet({ onClose, projectInternalId }: Props) { // claimCode is the identifer used to poll for the status of the mint // Once we kick off the mint, the backend returns a claim code from Highlight that we can use to check the status of the mint - const [claimCode, setClaimCode] = usePersistedState(MCHX_CLAIM_CODE_KEY, ''); + const [claimCode, setClaimCode] = usePersistedState(`${projectInternalId}_claim_code`, ''); + + const { data } = useSanityDataContext(); + const projectData = useMemo(() => { + return data?.mintProjects.find((document) => document.internalId === projectInternalId); + }, [data, projectInternalId]); + console.log({ projectData }); + + if (!projectData) { + // TODO decide best way to handle missing data + return null; + } if (claimCode) { - return ; + return ( + + ); } - return ; + return ( + + ); } diff --git a/apps/mobile/src/components/Mint/MintCampaign/MintCampaignPostTransaction.tsx b/apps/mobile/src/components/Mint/MintCampaign/MintCampaignPostTransaction.tsx index 4099032707..bc56ca7594 100644 --- a/apps/mobile/src/components/Mint/MintCampaign/MintCampaignPostTransaction.tsx +++ b/apps/mobile/src/components/Mint/MintCampaign/MintCampaignPostTransaction.tsx @@ -15,6 +15,7 @@ import { SpinnerIcon } from 'src/icons/SpinnerIcon'; import { Button } from '~/components/Button'; import { BaseM, TitleS } from '~/components/Text'; +import { MintProject } from '~/contexts/SanityDataContext'; import { HighlightTxStatus, MintCampaignPostTransactionMintStatusQuery, @@ -26,9 +27,11 @@ import { NftDetailAsset } from '../../../screens/NftDetailScreen/NftDetailAsset/ export default function MintCampaignPostTransaction({ claimCode, onClose, + projectData, }: { claimCode: string; - onClose: () => void; + onClose?: () => void; + projectData: MintProject; }) { const [state, setState] = useState('TX_PENDING'); // TODO: Fix any - prioritizing merging atm @@ -119,7 +122,9 @@ export default function MintCampaignPostTransaction({ }); } - onClose(); + if (onClose) { + onClose(); + } // close bottom sheet }, [navigation, onClose, token?.dbid]); @@ -129,7 +134,9 @@ export default function MintCampaignPostTransaction({ if (token?.definition?.community) { navigateToCommunity(token?.definition?.community); } - onClose(); + if (onClose) { + onClose(); + } }, [navigateToCommunity, onClose, token?.definition?.community]); if (state === 'TOKEN_SYNCED' && token) { @@ -137,7 +144,12 @@ export default function MintCampaignPostTransaction({ Congratulations! - You collected {`${token?.definition?.name ?? 'Radiance'} by MCHX`} + + You collected{' '} + {`${token?.definition?.name ?? projectData.collectionName} by ${ + projectData.artistName + }`} + Thank you for using the Gallery mobile app. Share your unique piece with others below! @@ -173,7 +185,7 @@ export default function MintCampaignPostTransaction({ {state === 'TX_PENDING' ? 'Your new artwork is being minted onchain. This should take less than a minute.' - : 'Revealing your unique artwork. It will be ready to view in a moment!'} + : 'Revealing your artwork. It will be ready to view in a moment!'} @@ -183,7 +195,7 @@ export default function MintCampaignPostTransaction({ size="s" colorOverride={{ lightMode: colors.shadow, darkMode: colors.shadow }} /> - + {error && {error}} @@ -191,22 +203,22 @@ export default function MintCampaignPostTransaction({ ); } -const COPY = [ - 'Anton Dubrovin, aka MCHX, was born in Kazakhstan and is currently based in Georgia.', - 'Anton is a digital artist known for experimenting with colors and form.', - 'Anton uses color as a universal channel of emotional connection and self-exploration.', - 'For this project, MCHX created over 60 unique color modes and used a circle as the central object due to its universal symbolism of unity and integrity.', - 'This work leverages Javascript, GLSL, and Display P3 wide-gamut to explore emotional connection through color.', - "Anton's diverse inspiration comes from 20th-century abstraction, Abstract Expressionism, Color Field artists, nature, music, and the internet.", - 'In his free time, Anton enjoys taking walks, reading, and watching Japanese anime and dramas.', - 'Anton has been creating art since 2016, but entered the NFT and Web3 space in 2020.', - 'Anton believes in the exchange of energy inherent in blockchain interactions and his work carries imprints of his emotional states or needs at the time of creation.', -]; +// const COPY = [ +// 'Anton Dubrovin, aka MCHX, was born in Kazakhstan and is currently based in Georgia.', +// 'Anton is a digital artist known for experimenting with colors and form.', +// 'Anton uses color as a universal channel of emotional connection and self-exploration.', +// 'For this project, MCHX created over 60 unique color modes and used a circle as the central object due to its universal symbolism of unity and integrity.', +// 'This work leverages Javascript, GLSL, and Display P3 wide-gamut to explore emotional connection through color.', +// "Anton's diverse inspiration comes from 20th-century abstraction, Abstract Expressionism, Color Field artists, nature, music, and the internet.", +// 'In his free time, Anton enjoys taking walks, reading, and watching Japanese anime and dramas.', +// 'Anton has been creating art since 2016, but entered the NFT and Web3 space in 2020.', +// 'Anton believes in the exchange of energy inherent in blockchain interactions and his work carries imprints of his emotional states or needs at the time of creation.', +// ]; const FADE_DURATION = 250; const TEXT_DURATION = 8000; -function LoadingStateMessage() { +function LoadingStateMessage({ funFacts }: { funFacts: string[] }) { const [index, setIndex] = useState(0); const fadeInOpacity = useSharedValue(1); @@ -235,18 +247,18 @@ function LoadingStateMessage() { const updateDisplayedMessage = async () => { fadeOut(); await new Promise((resolve) => setTimeout(resolve, FADE_DURATION)); - setIndex((index) => (index + 1) % COPY.length); + setIndex((index) => (index + 1) % funFacts.length); fadeIn(); }; const interval = setInterval(updateDisplayedMessage, TEXT_DURATION); return () => clearInterval(interval); - }, [fadeIn, fadeOut]); + }, [fadeIn, fadeOut, funFacts.length]); return ( - {COPY[index]} + {funFacts[index]} ); diff --git a/apps/mobile/src/components/Mint/MintCampaign/MintCampaignPreTransaction.tsx b/apps/mobile/src/components/Mint/MintCampaign/MintCampaignPreTransaction.tsx index c6a0d26a3e..912115785d 100644 --- a/apps/mobile/src/components/Mint/MintCampaign/MintCampaignPreTransaction.tsx +++ b/apps/mobile/src/components/Mint/MintCampaign/MintCampaignPreTransaction.tsx @@ -2,25 +2,25 @@ import { Suspense, useCallback, useEffect, useMemo, useState } from 'react'; import { Image, View } from 'react-native'; import { graphql, useLazyLoadQuery } from 'react-relay'; import { contexts } from 'shared/analytics/constants'; -import { MCHX_CLAIM_CODE_KEY } from 'src/constants/storageKeys'; import { useHighlightClaimMint } from 'src/hooks/useHighlightClaimMint'; import usePersistedState from 'src/hooks/usePersistedState'; import { Button } from '~/components/Button'; import { BaseM, BaseS, TitleLItalic, TitleS } from '~/components/Text'; +import { MintProject } from '~/contexts/SanityDataContext'; import { MintCampaignPreTransactionQuery } from '~/generated/MintCampaignPreTransactionQuery.graphql'; -export const MCHX_MINT_CAMPAIGN_END_DATE = '2024-05-05T10:00:00-04:00'; - -const MCHX_COLLECTION_ID = '660d4342c6bc04d5dc5598e7'; - export default function MintCampaignPreTransaction({ setClaimCode, + projectInternalId, + projectData, }: { setClaimCode: (claimCode: string) => void; + projectInternalId: string; + projectData: MintProject; }) { const calculateTimeLeftText = useCallback(() => { - const endDate = new Date(MCHX_MINT_CAMPAIGN_END_DATE).getTime(); + const endDate = new Date(projectData.endDate).getTime(); const now = new Date().getTime(); const difference = endDate - now; @@ -33,13 +33,13 @@ export default function MintCampaignPreTransaction({ } return 'Campaign ended'; - }, []); + }, [projectData.endDate]); const isMintOver = useMemo(() => { - const endDate = new Date(MCHX_MINT_CAMPAIGN_END_DATE).getTime(); + const endDate = new Date(projectData.endDate).getTime(); const now = new Date().getTime(); return now > endDate; - }, []); + }, [projectData.endDate]); const [timeLeft, setTimeLeft] = useState(calculateTimeLeftText()); const [error, setError] = useState(''); @@ -54,7 +54,7 @@ export default function MintCampaignPreTransaction({ const { claimMint, isClamingMint } = useHighlightClaimMint(); - const [, setClaimCodeLocalStorage] = usePersistedState(MCHX_CLAIM_CODE_KEY, ''); + const [, setClaimCodeLocalStorage] = usePersistedState(`${projectInternalId}_claim_code`, ''); const handlePress = useCallback( async (recipientWalletId: string) => { @@ -64,7 +64,7 @@ export default function MintCampaignPreTransaction({ try { const claimCode = await claimMint({ - collectionId: MCHX_COLLECTION_ID, + collectionId: projectData.highlightProjectId, recipientWalletId, }); @@ -84,20 +84,17 @@ export default function MintCampaignPreTransaction({ setError('Something went wrong while minting. Please try again.'); } }, - [claimMint, setClaimCode, setClaimCodeLocalStorage] + [claimMint, projectData.highlightProjectId, setClaimCode, setClaimCodeLocalStorage] ); return ( - Exclusive free mint - - Thank you for downloading the Gallery app. As a token of our gratitude, we invite you to - mint Radiance by MCHX - on us ❤️ - + {projectData.title} + {projectData.description} @@ -107,7 +104,7 @@ export default function MintCampaignPreTransaction({ Limit 1 per user - Gallery x MCHX + Gallery x {projectData.artistName} @@ -128,7 +125,7 @@ export default function MintCampaignPreTransaction({ {error && {error}} - Note: Image above is an indicative preview only, final artwork will be uniquely generated. + Note: Image above is an indicative preview only, final artwork will be randomly generated. Powered by highlight.xyz diff --git a/apps/mobile/src/components/Notification/NotificationList.tsx b/apps/mobile/src/components/Notification/NotificationList.tsx index 9e95a63a29..79cf228000 100644 --- a/apps/mobile/src/components/Notification/NotificationList.tsx +++ b/apps/mobile/src/components/Notification/NotificationList.tsx @@ -69,7 +69,7 @@ export function NotificationList({ queryRef }: Props) { queryRef ); - const { announcement, fetchAnnouncement } = useAnnouncementContext(); + const { announcement, fetchAnnouncement, hasDismissedAnnouncement } = useAnnouncementContext(); const clearNotifications = useMobileClearNotifications(); const { isRefreshing, handleRefresh } = useRefreshHandle(refetch); @@ -83,14 +83,14 @@ export function NotificationList({ queryRef }: Props) { } } - if (announcement && announcement.active) { + if (announcement && announcement.active && !hasDismissedAnnouncement) { notifications.push({ id: 'announcement', kind: 'announcement' }); } notifications.reverse(); return notifications; - }, [announcement, query]); + }, [announcement, hasDismissedAnnouncement, query]); const loadMore = useCallback(() => { if (hasPrevious) { diff --git a/apps/mobile/src/components/Notification/Notifications/AnnouncementNotification.tsx b/apps/mobile/src/components/Notification/Notifications/AnnouncementNotification.tsx index a0ba56e53f..db6f524807 100644 --- a/apps/mobile/src/components/Notification/Notifications/AnnouncementNotification.tsx +++ b/apps/mobile/src/components/Notification/Notifications/AnnouncementNotification.tsx @@ -3,16 +3,27 @@ import { useCallback, useEffect } from 'react'; import { View } from 'react-native'; import FastImage from 'react-native-fast-image'; import { contexts } from 'shared/analytics/constants'; +import colors from 'shared/theme/colors'; +import { XMarkIcon } from 'src/icons/XMarkIcon'; -import { Button } from '~/components/Button'; import { GalleryTouchableOpacity } from '~/components/GalleryTouchableOpacity'; +import MintCampaignBottomSheet from '~/components/Mint/MintCampaign/MintCampaignBottomSheet'; import { BaseM } from '~/components/Text'; import { useAnnouncementContext } from '~/contexts/AnnouncementContext'; +import { useBottomSheetModalActions } from '~/contexts/BottomSheetModalContext'; -// display announcement content from Sanity +// Displays announcement content from Sanity export default function AnnouncementNotification() { - const { announcement, markAnnouncementAsSeen } = useAnnouncementContext(); - const handlePress = useCallback(() => {}, []); + const { announcement, markAnnouncementAsSeen, dismissAnnouncement } = useAnnouncementContext(); + const { showBottomSheetModal } = useBottomSheetModalActions(); + const handlePress = useCallback(() => { + showBottomSheetModal({ + content: , + }); + }, [announcement?.internal_id, showBottomSheetModal]); + const handleDismissPress = useCallback(() => { + dismissAnnouncement(); + }, [dismissAnnouncement]); useEffect(() => { markAnnouncementAsSeen(); @@ -25,10 +36,10 @@ export default function AnnouncementNotification() { } return ( - + - {announcement.title} - {announcement.description} + + {announcement.title} + + {announcement.description} - {announcement.ctaText && ( -