|
41 | 41 | </TabList> |
42 | 42 | </template> |
43 | 43 | <template #body> |
44 | | - <div v-if="displayAssets.length" class="relative size-full"> |
| 44 | + <!-- Loading state --> |
| 45 | + <div v-if="loading"> |
| 46 | + <ProgressSpinner class="absolute left-1/2 w-[50px] -translate-x-1/2" /> |
| 47 | + </div> |
| 48 | + <!-- Empty state --> |
| 49 | + <div v-else-if="!displayAssets.length"> |
| 50 | + <NoResultsPlaceholder |
| 51 | + icon="pi pi-info-circle" |
| 52 | + :title=" |
| 53 | + $t( |
| 54 | + activeTab === 'input' |
| 55 | + ? 'sideToolbar.noImportedFiles' |
| 56 | + : 'sideToolbar.noGeneratedFiles' |
| 57 | + ) |
| 58 | + " |
| 59 | + :message="$t('sideToolbar.noFilesFoundMessage')" |
| 60 | + /> |
| 61 | + </div> |
| 62 | + <!-- Content --> |
| 63 | + <div v-else class="relative size-full"> |
45 | 64 | <VirtualGrid |
46 | | - v-if="displayAssets.length" |
47 | 65 | :items="mediaAssetsWithKey" |
48 | 66 | :grid-style="{ |
49 | 67 | display: 'grid', |
50 | 68 | gridTemplateColumns: 'repeat(auto-fill, minmax(200px, 1fr))', |
51 | 69 | padding: '0.5rem', |
52 | 70 | gap: '0.5rem' |
53 | 71 | }" |
| 72 | + @approach-end="handleApproachEnd" |
54 | 73 | > |
55 | 74 | <template #item="{ item }"> |
56 | 75 | <MediaAssetCard |
|
66 | 85 | /> |
67 | 86 | </template> |
68 | 87 | </VirtualGrid> |
69 | | - <div v-else-if="loading"> |
70 | | - <ProgressSpinner |
71 | | - class="absolute left-1/2 w-[50px] -translate-x-1/2" |
72 | | - /> |
73 | | - </div> |
74 | | - <div v-else> |
75 | | - <NoResultsPlaceholder |
76 | | - icon="pi pi-info-circle" |
77 | | - :title=" |
78 | | - $t( |
79 | | - activeTab === 'input' |
80 | | - ? 'sideToolbar.noImportedFiles' |
81 | | - : 'sideToolbar.noGeneratedFiles' |
82 | | - ) |
83 | | - " |
84 | | - :message="$t('sideToolbar.noFilesFoundMessage')" |
85 | | - /> |
86 | | - </div> |
87 | 88 | </div> |
88 | 89 | </template> |
89 | 90 | <template #footer> |
|
147 | 148 | </template> |
148 | 149 |
|
149 | 150 | <script setup lang="ts"> |
| 151 | +import { useDebounceFn } from '@vueuse/core' |
150 | 152 | import ProgressSpinner from 'primevue/progressspinner' |
151 | 153 | import { useToast } from 'primevue/usetoast' |
152 | 154 | import { computed, onMounted, onUnmounted, ref, watch } from 'vue' |
@@ -291,6 +293,7 @@ watch( |
291 | 293 | activeTab, |
292 | 294 | () => { |
293 | 295 | clearSelection() |
| 296 | + // Reset pagination state when tab changes |
294 | 297 | void refreshAssets() |
295 | 298 | }, |
296 | 299 | { immediate: true } |
@@ -395,4 +398,15 @@ const handleDeleteSelected = async () => { |
395 | 398 | await deleteMultipleAssets(selectedAssets) |
396 | 399 | clearSelection() |
397 | 400 | } |
| 401 | +
|
| 402 | +const handleApproachEnd = useDebounceFn(async () => { |
| 403 | + if ( |
| 404 | + activeTab.value === 'output' && |
| 405 | + !isInFolderView.value && |
| 406 | + outputAssets.hasMore.value && |
| 407 | + !outputAssets.isLoadingMore.value |
| 408 | + ) { |
| 409 | + await outputAssets.loadMore() |
| 410 | + } |
| 411 | +}, 300) |
398 | 412 | </script> |
0 commit comments