feat(FontVirtualList): move logic related to loading next batch of fonts to the FontVirtualContainer

This commit is contained in:
Ilia Mashkov
2026-02-15 22:56:37 +03:00
parent bc56265717
commit c2d0992015
2 changed files with 40 additions and 58 deletions

View File

@@ -3,7 +3,7 @@
- Renders a virtualized list of fonts - Renders a virtualized list of fonts
- Handles font registration with the manager - Handles font registration with the manager
--> -->
<script lang="ts" generics="T extends UnifiedFont"> <script lang="ts">
import { import {
Skeleton, Skeleton,
VirtualList, VirtualList,
@@ -11,26 +11,23 @@ import {
import type { ComponentProps } from 'svelte'; import type { ComponentProps } from 'svelte';
import { fade } from 'svelte/transition'; import { fade } from 'svelte/transition';
import { getFontUrl } from '../../lib'; import { getFontUrl } from '../../lib';
import type { FontConfigRequest } from '../../model';
import { import {
type FontConfigRequest,
type UnifiedFont, type UnifiedFont,
appliedFontsManager, appliedFontsManager,
unifiedFontStore,
} from '../../model'; } from '../../model';
interface Props extends interface Props extends
Omit< Omit<
ComponentProps<typeof VirtualList<T>>, ComponentProps<typeof VirtualList<UnifiedFont>>,
'onVisibleItemsChange' 'items' | 'total' | 'isLoading' | 'onVisibleItemsChange' | 'onNearBottom'
> >
{ {
/** /**
* Callback for when visible items change * Callback for when visible items change
*/ */
onVisibleItemsChange?: (items: T[]) => void; onVisibleItemsChange?: (items: UnifiedFont[]) => void;
/**
* Callback for when near bottom is reached
*/
onNearBottom?: (lastVisibleIndex: number) => void;
/** /**
* Weight of the font * Weight of the font
*/ */
@@ -38,23 +35,20 @@ interface Props extends
* Weight of the font * Weight of the font
*/ */
weight: number; weight: number;
/**
* Whether the list is in a loading state
*/
isLoading?: boolean;
} }
let { let {
items,
children, children,
onVisibleItemsChange, onVisibleItemsChange,
onNearBottom,
weight, weight,
isLoading = false,
...rest ...rest
}: Props = $props(); }: Props = $props();
function handleInternalVisibleChange(visibleItems: T[]) { const isLoading = $derived(
unifiedFontStore.isFetching || unifiedFontStore.isLoading,
);
function handleInternalVisibleChange(visibleItems: UnifiedFont[]) {
const configs: FontConfigRequest[] = []; const configs: FontConfigRequest[] = [];
visibleItems.forEach(item => { visibleItems.forEach(item => {
@@ -77,9 +71,32 @@ function handleInternalVisibleChange(visibleItems: T[]) {
// onVisibleItemsChange?.(visibleItems); // onVisibleItemsChange?.(visibleItems);
} }
function handleNearBottom(lastVisibleIndex: number) { /**
// Forward the call to any external listener * Load more fonts by moving to the next page
onNearBottom?.(lastVisibleIndex); */
function loadMore() {
if (
!unifiedFontStore.pagination.hasMore
|| unifiedFontStore.isFetching
) {
return;
}
unifiedFontStore.nextPage();
}
/**
* Handle scroll near bottom - auto-load next page
*
* Triggered by VirtualList when the user scrolls within 5 items of the end
* of the loaded items. Only fetches if there are more pages available.
*/
function handleNearBottom(_lastVisibleIndex: number) {
const { hasMore } = unifiedFontStore.pagination;
// VirtualList already checks if we're near the bottom of loaded items
if (hasMore && !unifiedFontStore.isFetching) {
loadMore();
}
} }
</script> </script>
@@ -99,10 +116,11 @@ function handleNearBottom(lastVisibleIndex: number) {
</div> </div>
{:else} {:else}
<VirtualList <VirtualList
{items} items={unifiedFontStore.fonts}
{...rest} total={unifiedFontStore.pagination.total}
onVisibleItemsChange={handleInternalVisibleChange} onVisibleItemsChange={handleInternalVisibleChange}
onNearBottom={handleNearBottom} onNearBottom={handleNearBottom}
{...rest}
> >
{#snippet children(scope)} {#snippet children(scope)}
{@render children(scope)} {@render children(scope)}

View File

@@ -24,38 +24,6 @@ let innerHeight = $state(0);
// Is the component above the middle of the viewport? // Is the component above the middle of the viewport?
let isAboveMiddle = $state(false); let isAboveMiddle = $state(false);
const isLoading = $derived(
unifiedFontStore.isFetching || unifiedFontStore.isLoading,
);
/**
* Load more fonts by moving to the next page
*/
function loadMore() {
if (
!unifiedFontStore.pagination.hasMore
|| unifiedFontStore.isFetching
) {
return;
}
unifiedFontStore.nextPage();
}
/**
* Handle scroll near bottom - auto-load next page
*
* Triggered by VirtualList when the user scrolls within 5 items of the end
* of the loaded items. Only fetches if there are more pages available.
*/
function handleNearBottom(_lastVisibleIndex: number) {
const { hasMore } = unifiedFontStore.pagination;
// VirtualList already checks if we're near the bottom of loaded items
if (hasMore && !unifiedFontStore.isFetching) {
loadMore();
}
}
/** /**
* Calculate display range for pagination info * Calculate display range for pagination info
*/ */
@@ -83,13 +51,9 @@ const checkPosition = throttle(() => {
<div bind:this={wrapper}> <div bind:this={wrapper}>
<FontVirtualList <FontVirtualList
items={unifiedFontStore.fonts}
total={unifiedFontStore.pagination.total}
onNearBottom={handleNearBottom}
itemHeight={220} itemHeight={220}
useWindowScroll={true} useWindowScroll={true}
weight={controlManager.weight} weight={controlManager.weight}
{isLoading}
> >
{#snippet children({ {#snippet children({
item: font, item: font,