Re-layout the Masonry grid quicker after changes.

Watch more changes that might require a re-layout, but debounce
re-layouts to avoid chaos (500ms).
This commit is contained in:
Marcel Hellkamp 2023-07-28 19:26:30 +02:00
parent 1be255ec4c
commit b9d0c9f677

View File

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, inject, onBeforeUnmount, onMounted, onUpdated, ref, watch } from 'vue'; import { computed, inject, onBeforeUnmount, onMounted, onUpdated, ref, watch } from 'vue';
import { useDocumentVisibility, usePreferredDark, useWindowSize, watchDebounced } from '@vueuse/core' import { createFilterWrapper, debounceFilter, useDocumentVisibility, usePreferredDark, useWindowSize } from '@vueuse/core'
import { type Config, type Post } from '@/types'; import { type Config, type Post } from '@/types';
import { loadConfig } from '@/config'; import { loadConfig } from '@/config';
@ -41,11 +41,13 @@ watch(visibilityState, () => {
restartUpdates() restartUpdates()
}) })
// Re-layout Masonry on dom updates or window size changes // Fix Masonry layout on updates, config changes or window resize events
const fixLayout = inject('redrawVueMasonry') as () => void const fixLayout = inject('redrawVueMasonry') as () => void
onUpdated(() => fixLayout())
const windowSize = useWindowSize() const windowSize = useWindowSize()
watchDebounced(windowSize.width, () => { fixLayout() }, { debounce: 500, maxWait: 1000 }) const layoutDebounce = debounceFilter(500, { maxWait: 500 })
const doFixLayoput = createFilterWrapper(layoutDebounce, () => fixLayout())
watch([windowSize.width, config, allPosts], doFixLayoput, { deep: true })
onUpdated(doFixLayoput)
// Watch for a theme changes // Watch for a theme changes
const isDarkPrefered = usePreferredDark() const isDarkPrefered = usePreferredDark()
@ -201,8 +203,8 @@ const privacyLink = computed(() => {
<div v-else-if="filteredPosts.length === 0 && updateInProgress">Loading first posts ...</div> <div v-else-if="filteredPosts.length === 0 && updateInProgress">Loading first posts ...</div>
<div v-else-if="filteredPosts.length === 0">Nothing there yet ...</div> <div v-else-if="filteredPosts.length === 0">Nothing there yet ...</div>
<div v-else v-masonry transition-duration="1s" item-selector=".wall-item" percent-position="true" id="wall"> <div v-else v-masonry transition-duration="1s" item-selector=".wall-item" percent-position="true" id="wall">
<Card v-masonry-tile class="wall-item secret-hover" v-for="post in filteredPosts" :key="post.id" <Card v-masonry-tile class="wall-item secret-hover" v-for="post in filteredPosts" :key="post.id" :post="post"
:post="post" :config="config"> :config="config">
<template v-slot:topleft> <template v-slot:topleft>
<div class="dropdown secret"> <div class="dropdown secret">
@ -218,7 +220,7 @@ const privacyLink = computed(() => {
</ul> </ul>
</div> </div>
</template> </template>
</Card> </Card>
</div> </div>
</main> </main>