Skip to content

Commit

Permalink
Merge pull request #10334 from hassnian/issue-10312
Browse files Browse the repository at this point in the history
fix: It is still possible to mint two identic images
  • Loading branch information
prury authored Jun 19, 2024
2 parents c1d2aef + cc42b3f commit 0230940
Show file tree
Hide file tree
Showing 11 changed files with 88 additions and 84 deletions.
6 changes: 3 additions & 3 deletions components/collection/drop/GenerativeLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@

<LazyCollectionDropCursorParty
:drop-alias="drop.alias"
:user-minted-count="mintedAmountForCurrentUser" />
:user-minted-count="userMintsCount" />

<LazyCollectionDropPartyModal />
</template>
Expand All @@ -89,8 +89,8 @@ const mdBreakpoint = 768
const emit = defineEmits(['mint'])
const { drop } = useDrop()
const { previewItem } = storeToRefs(useDropStore())
const { mintedAmountForCurrentUser, description } = useCollectionEntity()
const { previewItem, userMintsCount } = storeToRefs(useDropStore())
const { description } = useCollectionEntity()
const { width } = useWindowSize()
const { emitEvent, completeLastEvent } = useCursorDropEvents()
Expand Down
15 changes: 5 additions & 10 deletions components/collection/drop/GenerativePreview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,14 @@ import { NeoButton, NeoIcon } from '@kodadot1/brick'
import { sanitizeIpfsUrl } from '@/utils/ipfs'
import useGenerativeIframeData from '@/composables/drop/useGenerativeIframeData'
import { useDrop } from '@/components/drops/useDrops'
import useGenerativeDropMint, {
useCollectionEntity,
} from '@/composables/drop/useGenerativeDropMint'
import useGenerativeDropMint from '@/composables/drop/useGenerativeDropMint'
const { accountId } = useAuth()
const { chainSymbol, decimals } = useChain()
const { drop } = useDrop()
const dropStore = useDropStore()
const { userMintsCount, mintsCount } = storeToRefs(dropStore)
const { maxCount } = useGenerativeDropMint()
const { mintedAmountForCurrentUser } = useCollectionEntity()
const { imageDataPayload, imageDataLoaded } = useGenerativeIframeData()
const { formatted: formattedPrice } = useAmount(
computed(() => drop.value.price),
Expand All @@ -111,7 +109,7 @@ const mintedPercent = computed(() => {
if (!maxCount.value) {
return 0
}
return Math.round((dropStore.mintsCount / maxCount.value) * 100)
return Math.round((mintsCount.value / maxCount.value) * 100)
})
const displayUrl = computed(() => generativeImageUrl.value || drop.value?.image)
Expand All @@ -124,7 +122,7 @@ const generateNft = () => {
startTimer()
const previewItem = generatePreviewItem({
entropyRange: getEntropyRange(mintedAmountForCurrentUser.value),
entropyRange: getEntropyRange(userMintsCount.value),
accountId: accountId.value,
content: drop.value.content,
})
Expand All @@ -142,10 +140,7 @@ watch(imageDataLoaded, () => {
}
})
watch(
[accountId, () => drop.value.content, mintedAmountForCurrentUser],
generateNft,
)
watch([accountId, () => drop.value.content, userMintsCount], generateNft)
onMounted(() => {
setTimeout(generateNft, 500)
Expand Down
9 changes: 3 additions & 6 deletions components/collection/drop/MintButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@

<script setup lang="ts">
import { NeoButton } from '@kodadot1/brick'
import useGenerativeDropMint, {
useCollectionEntity,
} from '@/composables/drop/useGenerativeDropMint'
import useGenerativeDropMint from '@/composables/drop/useGenerativeDropMint'
import { useDropStore } from '@/stores/drop'
import { useDrop, useDropMinimumFunds } from '@/components/drops/useDrops'
import {
Expand All @@ -42,8 +40,7 @@ const { hasCurrentChainBalance } = useMultipleBalance()
const { drop } = useDrop()
const now = useNow()
const { mintCountAvailable, maxCount } = useGenerativeDropMint()
const { mintedAmountForCurrentUser } = useCollectionEntity()
const { amountToMint, previewItem } = storeToRefs(dropStore)
const { amountToMint, previewItem, userMintsCount } = storeToRefs(dropStore)
const { hasMinimumFunds } = useDropMinimumFunds()
const { holderOfCollection } = useHolderOfCollection()
Expand Down Expand Up @@ -140,7 +137,7 @@ const enabled = computed(() => {
case 'holder':
return isHolderAndEligible.value
case 'paid':
return maxCount.value > mintedAmountForCurrentUser.value
return maxCount.value > userMintsCount.value
default:
return false
}
Expand Down
8 changes: 6 additions & 2 deletions components/collection/drop/PaidGenerative.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
:status="status"
:is-error="isError"
@confirm="mintNft"
@close="closeMintModal"
@close="handleMintModalClose"
@list="handleList" />
</template>

Expand Down Expand Up @@ -104,9 +104,13 @@ const handleSubmitMint = async () => {
await massGenerate()
}
const handleMintModalClose = () => {
closeMintModal()
setTimeout(clearMassMint, NEO_MODAL_ANIMATION_DURATION)
}
const closeMintModal = () => {
isMintModalActive.value = false
clearMassMint()
}
const submitMints = async () => {
Expand Down
25 changes: 7 additions & 18 deletions components/collection/drop/modal/PaidMint.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
<NeoModal
:value="modelValue"
:can-cancel="isSigningStep ? false : ['outside', 'escape']"
@close="onClose">
@close="close">
<ModalBody
:title="title"
:scrollable="false"
:loading="loading"
:custom-skeleton-title="preStepTitle"
:estimated-time="estimedTime"
@close="onClose">
@close="close">
<MintOverview
v-if="isMintOverviewStep"
ref="mintOverview"
Expand Down Expand Up @@ -156,13 +156,6 @@ const title = computed(() => {
const close = () => emit('close')
const onClose = () => {
close()
if (isSuccessfulDropStep.value) {
window.location.reload()
}
}
const handleModalClose = (completed: boolean) => {
if (completed) {
autoteleportCompleted.value = true
Expand Down Expand Up @@ -199,13 +192,9 @@ watchEffect(() => {
}
})
watchDebounced(
[() => props.modelValue, isAutoTeleportModalOpen],
([isOpen]) => {
if (!isOpen && !isAutoTeleportModalOpen.value) {
reset()
}
},
{ debounce: 500 }, // wait for the modal closing animation to finish
)
useModalIsOpenTracker({
isOpen: computed(() => props.modelValue),
onChange: reset,
and: [computed(() => !isAutoTeleportModalOpen.value)],
})
</script>
58 changes: 32 additions & 26 deletions components/drops/useDrops.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,58 +194,64 @@ export const fetchDropMintedCount = async (
}

const subscribeDropMintedCount = (
drop: Pick<DropItem, 'collection'>,
onChange: (count: number | undefined) => void,
{ drop, account }: { drop: Pick<DropItem, 'collection'>; account: string },
onChange: (params: { collection?: number; user?: number }) => void,
) => {
return useSubscriptionGraphql({
query: `
collectionEntityById(id: "${drop.collection}") {
nftCount
nfts(where: { issuer_eq: "${account}" }) {
id
}
}
`,
onChange: ({ data }) => {
onChange(data.collectionEntityById?.nftCount)
onChange({
collection: data.collectionEntityById?.nftCount,
user: data.collectionEntityById?.nfts?.length,
})
},
})
}

export const useDropStatus = (
drop: WritableComputedRef<{ collection: string; chain: Prefix }>,
) => {
const dropStore = useDropStore()
const { mintsCount, userMintsCount } = storeToRefs(useDropStore())
const { accountId } = useAuth()

const dropStatusSubscription = ref<{
collection: string | undefined
account: string | undefined
unsubscribe: () => void
}>({
account: undefined,
collection: undefined,
unsubscribe: () => {},
})

const mintsCount = computed({
get: () => dropStore.mintsCount,
set: (value) => dropStore.setMintedDropCount(value),
})

const subscribeDropStatus = () => {
watch(
() => drop.value,
(drop) => {
if (drop) {
if (drop.collection !== dropStatusSubscription.value.collection) {
dropStatusSubscription.value.unsubscribe?.()
}

dropStatusSubscription.value.collection = drop.collection
dropStatusSubscription.value.unsubscribe = subscribeDropMintedCount(
drop,
(count) => {
mintsCount.value = count ?? 0
},
)
watch([() => drop.value, accountId], ([drop, account]) => {
if (drop) {
if (
drop.collection !== dropStatusSubscription.value.collection ||
account !== dropStatusSubscription.value.account
) {
dropStatusSubscription.value.unsubscribe?.()
}
},
)

dropStatusSubscription.value.collection = drop.collection
dropStatusSubscription.value.account = accountId.value
dropStatusSubscription.value.unsubscribe = subscribeDropMintedCount(
{ drop, account: accountId.value },
({ collection, user }) => {
mintsCount.value = collection ?? 0
userMintsCount.value = user ?? 0
},
)
}
})

onUnmounted(() => dropStatusSubscription.value.unsubscribe?.())
}
Expand Down
9 changes: 5 additions & 4 deletions components/profile/create/Modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,13 @@ const loginWithFarcaster = async () => {
farcasterUserData.value = userData.data
}
watch(
() => props.modelValue,
() => {
useModalIsOpenTracker({
isOpen: computed(() => props.modelValue),
onChange: () => {
stage.value = initialStep.value
},
)
})
watch(documentVisibility, (current, previous) => {
if (
current === 'visible' &&
Expand Down
5 changes: 0 additions & 5 deletions composables/drop/useGenerativeDropMint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export type DropCollectionById = {
nftCount: number
nfts: { sn: string }[]
}
nftEntitiesConnection: { totalCount: number }
}

function useCollectionData(collectionId, client) {
Expand Down Expand Up @@ -56,9 +55,6 @@ export function useCollectionEntity() {
client,
)
const maxCount = computed(() => collectionData.value?.collectionEntity?.max)
const mintedAmountForCurrentUser = computed(
() => collectionData.value?.nftEntitiesConnection?.totalCount ?? 0,
)
const description = computed(
() => collectionData.value?.collectionEntity?.meta?.description ?? '',
)
Expand All @@ -71,7 +67,6 @@ export function useCollectionEntity() {

return {
maxCount,
mintedAmountForCurrentUser,
description,
collectionName,
nftCount,
Expand Down
25 changes: 25 additions & 0 deletions composables/useModalIsOpenTracker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export const NEO_MODAL_ANIMATION_DURATION = 200

export default ({
onChange,
isOpen,
and = [],
onAnimationEnded = true,
onClose = true,
}: {
onChange: () => void
isOpen: Ref<boolean>
and?: Ref<boolean>[]
onAnimationEnded?: boolean
onClose?: boolean
}) => {
watchDebounced(
[isOpen, () => and],
([isOpen, and]) => {
if (!isOpen === onClose && and.every(Boolean)) {
onChange()
}
},
{ debounce: onAnimationEnded ? NEO_MODAL_ANIMATION_DURATION : 0 },
)
}
7 changes: 0 additions & 7 deletions queries/subsquid/general/unlockableCollectionById.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,4 @@ query unlockableCollectionById(
...subsquidNft
}
}

nftEntitiesConnection(
orderBy: id_ASC
where: { burned_eq: false, collection: { id_eq: $id }, AND: $search }
) {
totalCount
}
}
5 changes: 2 additions & 3 deletions stores/drop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ interface State {
runtimeMintCount: number
drop: DropItem
mintsCount: number
userMintsCount: number
claimedNFT: DropMintedNft | undefined
previewItem: GenerativePreviewItem | undefined
// massmint
Expand All @@ -42,6 +43,7 @@ export const useDropStore = defineStore('drop', {
runtimeMintCount: 0,
drop: { ...DEFAULT_DROP, chain: urlPrefix.value },
mintsCount: 0,
userMintsCount: 0,
claimedNFT: undefined,
amountToMint: 1,
toMintNFTs: [],
Expand Down Expand Up @@ -70,9 +72,6 @@ export const useDropStore = defineStore('drop', {
setDrop(payload: DropItem) {
this.drop = payload
},
setMintedDropCount(payload: number) {
this.mintsCount = payload
},
setClaimedNFT(payload: DropMintedNft | undefined) {
this.claimedNFT = payload
},
Expand Down

0 comments on commit 0230940

Please sign in to comment.