Skip to content

Commit

Permalink
feat(inscription, metaPin): add load more functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
AricRedemption committed Mar 27, 2024
1 parent de0cbe9 commit 3f87026
Show file tree
Hide file tree
Showing 10 changed files with 269 additions and 101 deletions.
23 changes: 23 additions & 0 deletions src/components/LoadingIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts" setup>
const props = defineProps<{
class?: string
}>()
console.log(props)
</script>

<template>
<svg
fill="none"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
:class="['animate-spin h-5 w-5 text-white', props.class]"
>
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path
class="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
></path>
</svg>
</template>
14 changes: 7 additions & 7 deletions src/pages/nfts/BRCTokenList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,18 @@ import { getAddress } from '@/lib/account'
import { ArrowDownLeftIcon } from '@heroicons/vue/20/solid'
import { type Inscription, useBRCInscriptionsQuery } from '@/queries/inscribe'
const sizeRef = ref(10)
const addressRef = ref()
const size = ref(10)
const address = ref()
const cursorRef = ref(0)
const router = useRouter()
const inscriptions = ref<Inscription[]>([])
getAddress('btc').then((address) => {
addressRef.value = address
getAddress('btc').then((_address) => {
address.value = _address
})
const { isLoading, data: inscriptionsData } = useBRCInscriptionsQuery(addressRef, cursorRef, sizeRef, {
enabled: computed(() => !!addressRef.value),
const { isLoading, data: inscriptionsData } = useBRCInscriptionsQuery(address, cursorRef, size, {
enabled: computed(() => !!address.value),
})
watch(inscriptionsData, () => {
Expand All @@ -44,7 +44,7 @@ const toBRC20Detail = (inscriptionId: string) => {
router.push({
name: 'brc20Detail',
params: {
address: addressRef.value,
address: address.value,
inscriptionId,
},
})
Expand Down
4 changes: 2 additions & 2 deletions src/pages/nfts/Index.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script lang="ts" setup>
import { ref } from 'vue'
import BRCTokenList from './BRCTokenList.vue'
import MetaIDPinList from './MetaIDPinList.vue'
import { useRoute, useRouter } from 'vue-router'
import { nftStore } from '@/stores/nftTypeStore'
import InscriptionList from './InscriptionList.vue'
import AccountItem from '../accounts/components/Item.vue'
import { Squares2X2Icon } from '@heroicons/vue/24/outline'
import { getCurrentAccount, type Account } from '@/lib/account'
Expand Down Expand Up @@ -82,7 +82,7 @@ function changeTab(index: number) {
</TabPanel> -->
<TabPanel>
<MvcCollectionPanel v-if="nftStore.selectedNFT.name === 'MetaContract'" />
<BRCTokenList v-else-if="nftStore.selectedNFT.name === 'Ordinals'" />
<InscriptionList v-else-if="nftStore.selectedNFT.name === 'Ordinals'" />
<MetaIDPinList v-else-if="nftStore.selectedNFT.name === 'MetaID Pin'" />
</TabPanel>
</TabPanels>
Expand Down
75 changes: 75 additions & 0 deletions src/pages/nfts/InscriptionList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<script setup lang="ts">
import dayjs from 'dayjs'
import { ref, computed } from 'vue'
import BRCToken from './BRCToken.vue'
import { useRouter } from 'vue-router'
import { getAddress } from '@/lib/account'
import LoadingIcon from '@/components/LoadingIcon.vue'
import { useInscriptionsInfiniteQuery } from '@/queries/inscribe'
const size = ref(10)
const address = ref()
const router = useRouter()
getAddress('btc').then((_address) => {
address.value = _address
})
const { data, isLoading, hasNextPage, fetchNextPage, isFetchingNextPage } = useInscriptionsInfiniteQuery(
address,
size,
{
enabled: computed(() => !!address.value),
}
)
const inscriptions = computed(() => (data.value ? data.value.pages.flatMap((page) => page.list) : []))
const toBRC20Detail = (inscriptionId: string) => {
router.push({
name: 'brc20Detail',
params: {
address: address.value,
inscriptionId,
},
})
}
</script>

<template>
<div class="space-y-4">
<div v-if="isLoading" class="w-full py-3 text-center text-sm text-gray-500">Ordinals loading...</div>
<div v-else-if="inscriptions.length">
<div class="px-3 py-4 grid grid-cols-3 gap-x-3 gap-y-7">
<div
v-for="inscription in inscriptions"
@click="toBRC20Detail(inscription.inscriptionId)"
class="flex flex-col items-center justify-center rounded-md cursor-pointer text-[#999999]"
>
<BRCToken :value="inscription.outputValue" :contentBody="inscription.contentBody" />
<span class="text-sm text-center mt-3 truncate" :title="'# ' + inscription.inscriptionNumber">{{
inscription.utxoHeight === 0 ? 'Uncomfirmed' : `# ${inscription.inscriptionNumber}`
}}</span>
<span class="text-xs text-center mt-1 h-[30px]">{{
dayjs(inscription.timestamp * 1000).format('YYYY/MM/DD HH:mm:ss')
}}</span>
</div>
</div>
<div
v-if="hasNextPage"
:disabled="isFetchingNextPage"
@click="() => fetchNextPage()"
:class="[
'text-gray-primary flex items-center gap-2 justify-center',
!isFetchingNextPage ? 'cursor-pointer hover:text-blue-500 hover:underline' : 'cursor-not-allowed',
]"
>
<span>Load more Ordinals</span>
<LoadingIcon v-if="isFetchingNextPage" class="!text-gray-primary" />
</div>
</div>
<div v-else class="w-full py-3 text-center text-sm text-gray-500">No Ordinals yet.</div>
</div>
</template>

<style lang="less" scoped></style>
65 changes: 41 additions & 24 deletions src/pages/nfts/MetaIDPinList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,64 @@ import { ref, computed } from 'vue'
import MetaPin from './MetaPin.vue'
import { useRouter } from 'vue-router'
import { getAddress } from '@/lib/account'
import { useMetaPinsQuery } from '@/queries/nfts'
import LoadingIcon from '@/components/LoadingIcon.vue'
import { useMetaPinsInfiniteQuery } from '@/queries/metaPin'
const addressRef = ref()
const cursorRef = ref(0)
const sizeRef = ref(10)
const size = ref(2)
const address = ref()
const router = useRouter()
getAddress('btc').then((address) => {
addressRef.value = address
getAddress('btc').then((_address) => {
address.value = _address
})
const { isLoading, data: metaPins } = useMetaPinsQuery(addressRef, cursorRef, sizeRef, {
enabled: computed(() => !!addressRef.value),
const { data, isLoading, hasNextPage, fetchNextPage, isFetchingNextPage } = useMetaPinsInfiniteQuery(address, size, {
enabled: computed(() => !!address.value),
})
const metaPins = computed(() => (data.value ? data.value.pages.flatMap((page) => page.metaPins) : []))
const toMetaPinDetail = (metaPinId: string) => {
router.push({
name: 'metaPinDetail',
params: { metaPinId, address: addressRef.value },
params: { metaPinId, address: address.value },
})
}
</script>

<template>
<div class="space-y-4">
<div v-if="isLoading" class="w-full py-3 text-center text-sm text-gray-500">MetaID Pin List loading...</div>
<div v-else-if="metaPins?.length" class="mt-12 px-3 py-4 grid grid-cols-3 gap-x-3 gap-y-7">
<div v-if="isLoading" class="w-full py-3 text-center text-sm text-gray-500">MetaID Pins loading...</div>
<div v-else-if="metaPins?.length">
<div class="mt-12 px-3 py-4 grid grid-cols-3 gap-x-3 gap-y-7">
<div
v-for="metaPin in metaPins"
@click="toMetaPinDetail(metaPin.id)"
class="flex flex-col items-center justify-center rounded-md cursor-pointer text-[#999999]"
>
<MetaPin
:content="metaPin.content"
:value="metaPin.outputValue"
:contentType="metaPin.contentType"
:contentSummary="metaPin.contentSummary"
/>
<span class="text-sm text-center mt-3 truncate" :title="'# ' + metaPin.number"># {{ metaPin.number }}</span>
<span class="text-xs text-center mt-1 h-[30px]">{{
metaPin.timestamp === 0 ? 'Uncomfirmed' : dayjs(metaPin.timestamp * 1000).format('YYYY/MM/DD HH:mm:ss')
}}</span>
</div>
</div>
<div
v-for="metaPin in metaPins"
@click="toMetaPinDetail(metaPin.id)"
class="flex flex-col items-center justify-center rounded-md cursor-pointer text-[#999999]"
v-if="hasNextPage"
:disabled="isFetchingNextPage"
@click="() => fetchNextPage()"
:class="[
'text-gray-primary flex items-center gap-2 justify-center',
!isFetchingNextPage ? 'cursor-pointer hover:text-blue-500 hover:underline' : 'cursor-not-allowed',
]"
>
<MetaPin
:content="metaPin.content"
:value="metaPin.outputValue"
:contentType="metaPin.contentType"
:contentSummary="metaPin.contentSummary"
/>
<span class="text-sm text-center mt-3 truncate" :title="'# ' + metaPin.number"># {{ metaPin.number }}</span>
<span class="text-xs text-center mt-1 h-[30px]">{{
metaPin.timestamp === 0 ? 'Uncomfirmed' : dayjs(metaPin.timestamp * 1000).format('YYYY/MM/DD HH:mm:ss')
}}</span>
<span>Load more MetaPins</span>
<LoadingIcon v-if="isFetchingNextPage" class="!text-gray-primary" />
</div>
</div>
<div v-else class="w-full py-3 text-center text-sm text-gray-500">No MetaID Pins yet</div>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/nfts/MetaPinDetail.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script setup lang="ts">
import dayjs from 'dayjs'
import { computed, ref } from 'vue'
import { useMetaPinQuery } from '@/queries/nfts'
import { useRoute, useRouter } from 'vue-router'
import { shortestAddress } from '@/lib/formatters'
import { useMetaPinQuery } from '@/queries/metaPin'
const { params } = useRoute()
const router = useRouter()
Expand Down
2 changes: 1 addition & 1 deletion src/pages/nfts/SendNFT.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import { ref } from 'vue'
import { useRoute } from 'vue-router'
import type { Psbt } from 'bitcoinjs-lib'
import { getMetaPin } from '@/queries/nfts'
import { BtcWallet } from '@/lib/wallets/btc'
import { getMetaPin } from '@/queries/metaPin'
import CopyIcon from '@/assets/icons/copy.svg'
import { useQueryClient } from '@tanstack/vue-query'
import { UTXO, getInscriptionUtxo } from '@/queries/utxos'
Expand Down
38 changes: 37 additions & 1 deletion src/queries/inscribe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Buffer } from 'buffer'
import { getNet } from '@/lib/network'
import { Ref, ComputedRef } from 'vue'
import { metaletApiV3 } from './request'
import { useQuery } from '@tanstack/vue-query'
import { useQuery, useInfiniteQuery } from '@tanstack/vue-query'

export interface PreInscribe {
count: number
Expand Down Expand Up @@ -110,6 +110,27 @@ export async function getBRCInscriptions(
})
}

export async function fetchCInscriptions(
address: string,
cursor: number,
size: number
): Promise<{ list: Inscription[]; nextCursor: number | null }> {
const net = getNet()
const { list, total } = await metaletApiV3<{ list: Inscription[]; total: number }>('/address/inscriptions').get({
net,
address,
cursor: `${cursor}`,
size: `${size}`,
})

cursor += size

return {
list,
nextCursor: cursor > total ? null : cursor,
}
}

export async function getBRCInscriptionInfo(inscriptionId: string): Promise<Inscription> {
const net = getNet()
const {
Expand All @@ -121,6 +142,21 @@ export async function getBRCInscriptionInfo(inscriptionId: string): Promise<Insc
return inscription
}

export const useInscriptionsInfiniteQuery = (
address: Ref<string>,
size: Ref<number>,
options: { enabled: ComputedRef<boolean> }
) => {
return useInfiniteQuery(
['Inscriptions', { address, size }],
({ pageParam: cursor = 0 }) => fetchCInscriptions(address.value, cursor, size.value),
{
getNextPageParam: (lastPage) => lastPage.nextCursor,
...options,
}
)
}

export const useBRCInscriptionsQuery = (
address: Ref<string>,
page: Ref<number>,
Expand Down
Loading

0 comments on commit 3f87026

Please sign in to comment.