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

Infinite scroll for all views #2859

Merged
merged 17 commits into from
Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from 14 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
11 changes: 6 additions & 5 deletions components/rmrk/Collection/List/CollectionList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@resetPage="resetPage"
hideSearch
:sortOption="collectionSortOption">
<b-field>
<b-field class="is-flex">
<Layout class="mr-5" @change="onResize" />
<Pagination
hasMagicBtn
Expand All @@ -20,10 +20,10 @@
</Search>

<div>
<infinite-loading
<InfiniteLoading
v-if="startPage > 1 && !isLoading && total > 0"
direction="top"
@infinite="reachTopHandler"></infinite-loading>
@infinite="reachTopHandler"></InfiniteLoading>
<div
id="infinite-scroll-container"
class="columns is-multiline"
Expand Down Expand Up @@ -56,9 +56,9 @@
</div>
</div>
</div>
<infinite-loading
<InfiniteLoading
v-if="canLoadNextPage && !isLoading && total > 0"
@infinite="reachBottomHandler"></infinite-loading>
@infinite="reachBottomHandler"></InfiniteLoading>
</div>
</div>
</template>
Expand Down Expand Up @@ -95,6 +95,7 @@ interface Image extends HTMLImageElement {
const components = {
GalleryCardList: () =>
import('@/components/rmrk/Gallery/GalleryCardList.vue'),
InfiniteLoading: () => import('vue-infinite-loading'),
Search: () =>
import('@/components/rmrk/Gallery/Search/SearchBarCollection.vue'),
Money: () => import('@/components/shared/format/Money.vue'),
Expand Down
7 changes: 6 additions & 1 deletion components/rmrk/ExploreLayout/ExploreLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,13 @@ export default class ExploreLayout extends mixins(PrefixMixin) {

set selectedTab(val) {
this.$route.query.page = ''
let queryOptions: { tab: string; search?: string | (string | null)[] } = {
let queryOptions: {
tab: string
page: string
search?: string | (string | null)[]
} = {
tab: val,
page: '1',
}
if (this.$route.query.search) {
queryOptions.search = this.$route.query.search
Expand Down
133 changes: 84 additions & 49 deletions components/rmrk/Gallery/CollectionItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,17 @@
</b-field>
</Search>

<InfiniteLoading
v-if="startPage > 1 && !isLoading && total > 0"
direction="top"
@infinite="reachTopHandler"></InfiniteLoading>
<GalleryCardList
:items="collection.nfts"
:items="nfts"
:listed="!!(searchQuery && searchQuery.listed)"
horizontalLayout />

<Pagination
class="py-5"
replace
v-if="activeTab === 'items'"
preserveScroll
:total="total"
v-model="currentValue"
:per-page="first" />
<InfiniteLoading
v-if="canLoadNextPage && !isLoading && total > 0"
@infinite="reachBottomHandler"></InfiniteLoading>
</b-tab-item>
<b-tab-item label="Chart" value="chart">
<CollectionPriceChart :priceData="priceData" />
Expand Down Expand Up @@ -147,11 +145,13 @@ import PrefixMixin from '~/utils/mixins/prefixMixin'
import { getCloudflareImageLinks } from '~/utils/cachingStrategy'
import { mapOnlyMetadata } from '~/utils/mappers'
import CreatedAtMixin from '@/utils/mixins/createdAtMixin'
import InfiniteScrollMixin from '~/utils/mixins/infiniteScrollMixin'
import { CollectionChartData as ChartData } from '@/utils/chart'
import { mapDecimals } from '@/utils/mappers'
import { notificationTypes, showNotification } from '@/utils/notification'
import allCollectionSaleEvents from '@/queries/rmrk/subsquid/allCollectionSaleEvents.graphql'
import { sortedEventByDate } from '~/utils/sorting'
import { Debounce } from 'vue-debounce-decorator'

const tabsWithCollectionEvents = ['history', 'holders', 'flippers']

Expand All @@ -175,29 +175,32 @@ const components = {
CommonHolderTable: () =>
import('@/components/rmrk/Gallery/Holder/Holder.vue'),
Flipper: () => import('@/components/rmrk/Gallery/Flipper.vue'),
InfiniteLoading: () => import('vue-infinite-loading'),
}
@Component<CollectionItem>({
components,
})
export default class CollectionItem extends mixins(
ChainMixin,
PrefixMixin,
CreatedAtMixin
CreatedAtMixin,
InfiniteScrollMixin
) {
@Ref('tabsContainer') readonly tabsContainer
private id = ''
private collection: CollectionWithMeta = emptyObject<CollectionWithMeta>()
public meta: CollectionMetadata = emptyObject<CollectionMetadata>()
private searchQuery: SearchQuery = {
search: '',
type: '',
sortBy: 'BLOCK_NUMBER_DESC',
listed: false,
}
private searchQuery: SearchQuery = Object.assign(
{
search: '',
type: '',
sortBy: (this.$route.query.sort as string) ?? 'BLOCK_NUMBER_DESC',
listed: false,
},
this.$route.query
)
public activeTab = 'items'
private currentValue = parseInt(this.$route.query?.page as string) || 1
private first = 16
protected total = 0
protected first = 16
protected totalListed = 0
protected stats: NFT[] = []
protected priceData: [ChartData[], ChartData[]] | [] = []
Expand All @@ -208,6 +211,8 @@ export default class CollectionItem extends mixins(
public priceChartData: [Date, number][][] = []
private openHistory = true
private openHolder = true
private isLoading = true
private nfts: NFT[] = []

collectionProfileSortOption: string[] = [
'BLOCK_NUMBER_DESC',
Expand All @@ -223,14 +228,6 @@ export default class CollectionItem extends mixins(
return this.priceData.length > 0
}

get isLoading(): boolean {
return Boolean(this.queryLoading)
}

get offset(): number {
return this.currentValue * this.first - this.first
}

get image(): string | undefined {
return this.meta.image
}
Expand All @@ -251,10 +248,6 @@ export default class CollectionItem extends mixins(
return this.openHolder
}

get nfts(): NFT[] {
return this.collection.nfts || []
}

get issuer(): string {
return this.collection.issuer || ''
}
Expand All @@ -271,6 +264,14 @@ export default class CollectionItem extends mixins(
return this.$store.state.preferences.showMintTimeCollection
}

set currentValue(page: number) {
this.gotoPage(page)
}

get currentValue() {
return this.currentPage
}

private buildSearchParam(checkForEmpty?): Record<string, unknown>[] {
const params: any[] = []

Expand All @@ -293,22 +294,40 @@ export default class CollectionItem extends mixins(
this.checkId()
this.checkActiveTab()
this.checkIfEmptyListed()
this.$apollo.addSmartQuery('collection', {
this.fetchPageData(this.startPage)
}

public async fetchPageData(page: number, loadDirection = 'down') {
if (this.isFetchingData) return false
this.isFetchingData = true
const result = await this.$apollo.query({
query: collectionById,
client: this.urlPrefix,
loadingKey: 'queryLoading',
manual: true,
variables: () => {
return {
id: this.id,
orderBy: this.searchQuery.sortBy,
search: this.buildSearchParam(),
first: this.first,
offset: this.offset,
}
variables: {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why u changed that from function to object?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because $apollo.query need variables to be an object.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

@Jarsen136 Jarsen136 Apr 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both function and object could work.

However, the query does not need to be 'reactive' in this case.
So I use the object to be the param. 🤔

And if you have other reasons to use 'function', I could change it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed my mind after doing some tries, because using function as variables could not work.

$apollo.query only accept 'object' in this case.

image

id: this.id,
orderBy: this.searchQuery.sortBy,
search: this.buildSearchParam(),
first: this.first,
offset: (page - 1) * this.first,
},
result: this.handleResult,
})
await this.handleResult(result, loadDirection)
this.isFetchingData = false
return true
}

@Debounce(500)
private resetPage() {
this.gotoPage(1)
}

private gotoPage(page: number) {
this.currentPage = page
this.startPage = page
this.endPage = page
this.nfts = []
this.isLoading = true
this.fetchPageData(page)
}

public async checkIfEmptyListed(): Promise<void> {
Expand Down Expand Up @@ -411,21 +430,32 @@ export default class CollectionItem extends mixins(
this.priceData = [listedPriceData, soldPriceData]
}

public async handleResult({ data }: any): Promise<void> {
public async handleResult(
{ data }: any,
loadDirection = 'down'
): Promise<void> {
const { collectionEntity } = data
if (!collectionEntity) {
this.$router.push({ name: 'errorcollection' })
return
}
this.firstMintDate = collectionEntity.createdAt
await getCloudflareImageLinks(
collectionEntity.nfts.nodes.map(mapOnlyMetadata)
).catch(this.$consola.warn)
const newNfts = collectionEntity.nfts.nodes

await getCloudflareImageLinks(newNfts.map(mapOnlyMetadata)).catch(
this.$consola.warn
)
this.collection = {
...collectionEntity,
nfts: collectionEntity.nfts.nodes,
nfts: newNfts,
}
if (loadDirection === 'up') {
this.nfts = newNfts.concat(this.nfts)
} else {
this.nfts = this.nfts.concat(newNfts)
}
this.total = collectionEntity.nfts.totalCount
this.isLoading = false

await this.fetchMetadata()
}
Expand Down Expand Up @@ -470,6 +500,11 @@ export default class CollectionItem extends mixins(
})
}

@Watch('searchQuery', { deep: true })
protected onSearchQueryChange() {
this.resetPage()
}

@Watch('activeTab')
protected onTabChange(val: string, oldVal: string): void {
let queryTab = this.$route.query.tab
Expand Down
Loading