sync details contain bugs

This commit is contained in:
m
2026-07-28 21:21:08 +02:00
parent 9c699446dc
commit 7af44152d7
7 changed files with 269 additions and 54 deletions
+12
View File
@@ -0,0 +1,12 @@
import { useState, useEffect } from 'react';
export function useDebounce<T>(value: T, delay: number): T {
const [debounced, setDebounced] = useState(value);
useEffect(() => {
const id = setTimeout(() => setDebounced(value), delay);
return () => clearTimeout(id);
}, [value, delay]);
return debounced;
}
+15 -14
View File
@@ -1,4 +1,4 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { useQuery, useMutation, useQueryClient, keepPreviousData } from '@tanstack/react-query';
import { apiClient } from '../api/client';
import { ENDPOINTS } from '../constants/api';
import type { UnifiedFileItem, PaginatedResponse, FileItem, Tag } from '../types';
@@ -27,7 +27,7 @@ function recordToUnifiedItem(record: ReturnType<typeof fileStore.getById>): Unif
};
}
function recordsToUnifiedItems(records: ReturnType<typeof fileStore.getPaginated>): {
function recordsToUnifiedItems(records: ReturnType<typeof fileStore.getRootFiles>): {
data: UnifiedFileItem[];
meta: { page: number; total: number };
} {
@@ -37,7 +37,7 @@ function recordsToUnifiedItems(records: ReturnType<typeof fileStore.getPaginated
};
}
export function useFiles(parentId?: string | null, page: number = 1, limit: number = 50) {
export function useFiles(parentId?: string | null, page: number = 1, limit: number = 100) {
const queryKey = parentId
? ['resources', parentId]
: ['resources', 'root', page, limit];
@@ -93,19 +93,20 @@ export function useFiles(parentId?: string | null, page: number = 1, limit: numb
})),
);
const cached = fileStore.getPaginated(page, limit);
return recordsToUnifiedItems(cached);
const cached = fileStore.getRootFiles();
return {
data: cached.files.map((r) => recordToUnifiedItem(r)!).filter(Boolean),
meta: { page, total: backendRes.meta?.total ?? cached.total },
};
},
placeholderData: keepPreviousData,
initialData: () => {
let records;
if (parentId) {
const children = fileStore.getChildrenByParent(parentId);
records = { files: children, total: children.length };
} else {
records = fileStore.getPaginated(page, limit);
}
if (records.files.length === 0) return undefined;
return recordsToUnifiedItems(records);
const cached = fileStore.getRootFiles();
if (cached.files.length === 0) return undefined;
return {
data: cached.files.map((r) => recordToUnifiedItem(r)!).filter(Boolean),
meta: { page: 0, total: cached.total },
};
},
staleTime: 30_000,
});
+42
View File
@@ -0,0 +1,42 @@
import { useCallback, useRef } from 'react';
import { apiClient } from '../api/client';
import { ENDPOINTS } from '../constants/api';
import { fileStore } from '../services/fileStore';
const MAX_POLL_MS = 120_000;
const POLL_INTERVAL = 3_000;
export type OcrPollResult = { resourceId: string; status: 'completed' | 'failed' | 'timeout' };
export function usePollOcr() {
const running = useRef<Set<string>>(new Set());
const pollOcr = useCallback(async (resourceId: string): Promise<OcrPollResult> => {
if (running.current.has(resourceId)) return { resourceId, status: 'failed' };
running.current.add(resourceId);
const start = Date.now();
try {
while (Date.now() - start < MAX_POLL_MS) {
try {
const detail = await apiClient.get<{ data: { ocrText?: string } }>(
`${ENDPOINTS.RESOURCES}/${resourceId}`,
);
const ocrText = detail.data?.ocrText;
if (ocrText && ocrText.length > 0) {
fileStore.updatePartial(resourceId, { ocrText });
return { resourceId, status: 'completed' };
}
} catch {
return { resourceId, status: 'failed' };
}
await new Promise((r) => setTimeout(r, POLL_INTERVAL));
}
return { resourceId, status: 'timeout' };
} finally {
running.current.delete(resourceId);
}
}, []);
return { pollOcr };
}