Skip to content

Commit

Permalink
feat: use infinite pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
AlejandroAkbal committed Apr 15, 2023
1 parent 1faab8e commit e3eefcb
Show file tree
Hide file tree
Showing 8 changed files with 394 additions and 456 deletions.
25 changes: 20 additions & 5 deletions app/router.scrollBehavior.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
export default function (to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else {
return { x: 0, y: 0 }
}
if (savedPosition) {
return savedPosition
}

// Skip scroll in Post pages
if (
to.name === from.name &&
to.path === from.path &&
to.hash === from.hash &&
// Is a Post page
['index'].includes(to.name) &&
// Has same [domain, tags], but different [page]
to.query.domain === from.query.domain &&
to.query.tags === from.query.tags &&
to.query.page !== from.query.page
) {
return false
}

return { x: 0, y: 0 }
}
246 changes: 70 additions & 176 deletions components/pages/posts/navigation/page/PostsControls.vue
Original file line number Diff line number Diff line change
@@ -1,73 +1,16 @@
<template>
<div>
<!-- Normal controls -->
<template v-if='!getUserSettings.infiniteLoad.value || forceNormalControls'>
<div
:class="{
'fixed inset-x-0 bottom-0 z-10 mx-auto max-w-3xl p-2 sm:p-4 lg:p-6':
getUserSettings.hoverControls.value
}"
>
<div class='material-container flex justify-around p-2 text-center'>
<!-- Previous page -->
<button
aria-label='Load previous page'
class='link'
title='Load previous page'
type='button'
@click='getPrevPage'
>
<span class='text-white'>&larr;</span> Prev
</button>

<!-- Get specific page -->
<button
aria-label='Load specific page'
class='link'
title='Load specific page'
type='button'
@click='setSpecificPage'
>
{{ currentPage }}
</button>

<!-- Next page -->
<button
aria-label='Load next page'
class='link'
title='Load next page'
type='button'
@click='getNextPage'
>
Next <span class='text-white'>&rarr;</span>
</button>
</div>
</div>

<!-- Space below all posts -->
<template v-if='getUserSettings.hoverControls.value'>
<div class='mt-6'>&nbsp;</div>
</template>
</template>

<!-- Infinite loading -->
<template v-else>
<div
v-intersect='{
handler: InfiniteLoadHandler,
options: {
threshold: [0, 0.25, 0.5, 0.75, 1.0]
}
}'
class='mx-auto py-12'
@click='InfiniteLoadHandler'
>
<p class='animate-pulse text-center text-gray-300'>
Stay here to load more posts...
</p>
</div>
</template>
</div>
<div
v-intersect="{
handler: InfiniteLoadHandler,
options: {
rootMargin: '600px'
}
}"
class="mx-auto py-12"
@click="InfiniteLoadHandler"
>
<p class="animate-pulse text-center text-gray-300">Loading more posts...</p>
</div>
</template>

<script>
Expand All @@ -80,112 +23,63 @@ import { Intersect } from 'vuetify/lib/directives/intersect'
import KeyboardNavigationMixin from '~/components/pages/posts/navigation/page/KeyboardNavigationMixin.js'
export default {
directives: {
Intersect
},
mixins: [KeyboardNavigationMixin],
props: {
currentPage: {
type: Number,
required: true
},
minimumPage: {
type: Number,
required: true
},
forceNormalControls: {
type: Boolean,
default: false
}
},
computed: {
...mapGetters('user', ['getUserSettings']),
...mapGetters('booru', ['getPosts'])
},
methods: {
getNextPage() {
this.setPage(this.currentPage + 1)
},
getPrevPage() {
this.setPage(this.currentPage - 1)
},
setSpecificPage() {
const specificPage = Number.parseInt(
prompt('What page do you want to go to?'),
10
)
if (isNaN(specificPage)) {
alert('Wrong input, only numbers please.')
return
}
this.setPage(specificPage)
},
isBelowMinimumPage(page) {
return page < this.minimumPage
},
setPage(page) {
if (this.isBelowMinimumPage(page)) {
return
}
this.$emit('setPage', page)
},
InfiniteLoadHandler(entries, observer) {
// Prevent loading more posts if there are no posts
if (!this.getPosts.length) {
return
}
const elementAttribute = 'data-is-visible'
const timeoutDelay = 1500
if (!entries || !entries.length) {
return
}
entries.forEach((entry) => {
// console.debug(entry.intersectionRatio)
if (!entry.isIntersecting || entry.intersectionRatio < 1) {
if (entry.target.getAttribute(elementAttribute)) {
// console.debug('Removed attribute from element.')
entry.target.removeAttribute(elementAttribute)
}
// console.debug('Element is not visible.')
return
}
entry.target.setAttribute(elementAttribute, true)
setTimeout(async () => {
const isVisible = entry.target.getAttribute(elementAttribute)
if (!isVisible) {
// console.debug('Timeout: Element does not have attribute.')
return
}
console.debug('Loading more posts...')
await this.getNextPage()
}, timeoutDelay)
})
}
}
directives: {
Intersect
},
mixins: [KeyboardNavigationMixin],
props: {
currentPage: {
type: Number,
required: true
},
minimumPage: {
type: Number,
required: true
}
},
computed: {
...mapGetters('user', ['getUserSettings']),
...mapGetters('booru', ['getPosts'])
},
methods: {
getNextPage() {
this.setPage(this.currentPage + 1)
},
getPrevPage() {
this.setPage(this.currentPage - 1)
},
isBelowMinimumPage(page) {
return page < this.minimumPage
},
setPage(page) {
if (this.isBelowMinimumPage(page)) {
return
}
this.$emit('setPage', page)
},
InfiniteLoadHandler(entries, observer) {
if (!entries || !entries.length) {
return
}
entries.forEach(async (entry) => {
if (!entry.isIntersecting) {
return
}
await this.getNextPage()
})
}
}
}
</script>
61 changes: 39 additions & 22 deletions components/pages/posts/post/FetchPostsMixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,43 @@ import { mapActions } from 'vuex'
import { debounce } from 'lodash-es'

export default {
async fetch() {
await this.debouncedFetchPosts()
},

// Fetch option
fetchOnServer: false,

watch: {
'$route.query': '$fetch'
},

methods: {
...mapActions('booru', ['fetchPosts']),

debouncedFetchPosts: debounce(
async function () {
await this.fetchPosts()
},
1,
{ maxWait: 5 }
)
}
async fetch() {
await this.debouncedFetchPosts('set')
},

// Fetch option
fetchOnServer: false,

watch: {
'$route.query': function (val, oldVal) {
let shouldSetPosts = false

// Set posts if an important part of the query changed, like domain and tags
if (val.domain !== oldVal.domain) {
shouldSetPosts = true
}

if (val.tags !== oldVal.tags) {
shouldSetPosts = true
}

const fetchMode = shouldSetPosts ? 'set' : 'concat'

this.debouncedFetchPosts(fetchMode)
}
},

methods: {
...mapActions('booru', ['fetchPosts']),

debouncedFetchPosts: debounce(
async function (mode) {
//

await this.fetchPosts(mode)
},
1,
{ maxWait: 5 }
)
}
}
2 changes: 0 additions & 2 deletions components/pages/posts/post/PostMedia.vue
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,6 @@ export default {
return
}
console.log(event.target.src)
// Add extra slash to URL
if (!this.media.retryLogic.tried.extraSlash) {
console.info('Adding extra slash...')
Expand Down
1 change: 1 addition & 0 deletions pages/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
</ul>

<PostsControls
v-if="getPosts.length"
:current-page="getPageID"
:minimum-page="getActiveBooruType.initialPageID"
@setPage="onPageChange"
Expand Down
Loading

0 comments on commit e3eefcb

Please sign in to comment.