mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-16 15:39:40 +02:00
- Add uload project with apps/web structure
- Reorganize from flat to monorepo structure
- Remove PocketBase binary and local data
- Update to pnpm and @uload/web namespace
- Add picture project to monorepo
- Remove embedded git repository
- Unify all package names to @{project}/{app} schema:
- @maerchenzauber/* (was @storyteller/*)
- @manacore/* (was manacore-*, manacore)
- @manadeck/* (was web, backend, manadeck)
- @memoro/* (was memoro-web, landing, memoro)
- @picture/* (already unified)
- @uload/web
- Add convenient dev scripts for all apps:
- pnpm dev:{project}:web
- pnpm dev:{project}:landing
- pnpm dev:{project}:mobile
- pnpm dev:{project}:backend
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
85 lines
2.6 KiB
TypeScript
85 lines
2.6 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { Image } from 'expo-image';
|
|
import { supabase } from '~/utils/supabase';
|
|
import { PAGINATION } from '~/constants';
|
|
import { FilterMode, ViewMode } from '~/types/gallery';
|
|
import { getThumbnailUrl, getSizeForViewMode } from '~/utils/image';
|
|
import { PREFETCH_DEBOUNCE_MS } from '~/constants/gallery';
|
|
|
|
type UseImagePrefetchProps = {
|
|
hasMore: boolean;
|
|
loading: boolean;
|
|
loadingMore: boolean;
|
|
itemsLength: number;
|
|
currentPage: number;
|
|
viewMode: ViewMode;
|
|
userId: string | undefined;
|
|
filterMode: FilterMode;
|
|
};
|
|
|
|
export function useImagePrefetch({
|
|
hasMore,
|
|
loading,
|
|
loadingMore,
|
|
itemsLength,
|
|
currentPage,
|
|
viewMode,
|
|
userId,
|
|
filterMode,
|
|
}: UseImagePrefetchProps) {
|
|
useEffect(() => {
|
|
if (!hasMore || loading || loadingMore || !userId) return;
|
|
|
|
// Prefetch when we have items and aren't at the end
|
|
const shouldPrefetch = itemsLength > 0 && hasMore;
|
|
|
|
if (!shouldPrefetch) return;
|
|
|
|
// Prefetch those images in the background
|
|
const prefetchNextPage = async () => {
|
|
try {
|
|
// Get the last few images that would be from the next page
|
|
const prefetchCount = Math.min(6, PAGINATION.GALLERY_PAGE_SIZE);
|
|
|
|
// Calculate what the next page would be
|
|
const nextPageNum = currentPage + 1;
|
|
|
|
let query = supabase
|
|
.from('images')
|
|
.select('id, public_url')
|
|
.eq('user_id', userId);
|
|
|
|
if (filterMode === 'favorites') {
|
|
query = query.eq('is_favorite', true);
|
|
}
|
|
|
|
const from = nextPageNum * PAGINATION.GALLERY_PAGE_SIZE;
|
|
const to = from + prefetchCount - 1;
|
|
|
|
const { data } = await query
|
|
.order('created_at', { ascending: false })
|
|
.range(from, to);
|
|
|
|
if (data && data.length > 0) {
|
|
// Prefetch thumbnails for next page
|
|
const thumbnailSize = getSizeForViewMode(viewMode);
|
|
data.forEach(img => {
|
|
if (img.public_url) {
|
|
const thumbnailUrl = getThumbnailUrl(img.public_url, thumbnailSize);
|
|
if (thumbnailUrl) {
|
|
Image.prefetch(thumbnailUrl);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
} catch (error) {
|
|
// Silent fail - prefetching is optional
|
|
console.debug('Prefetch failed (non-critical):', error);
|
|
}
|
|
};
|
|
|
|
// Debounce prefetching to avoid excessive requests
|
|
const timeoutId = setTimeout(prefetchNextPage, PREFETCH_DEBOUNCE_MS);
|
|
return () => clearTimeout(timeoutId);
|
|
}, [itemsLength, hasMore, currentPage, viewMode, userId, filterMode, loading, loadingMore]);
|
|
}
|