diff --git a/src/api/api.ts b/src/api/api.ts index f958f51..953802d 100644 --- a/src/api/api.ts +++ b/src/api/api.ts @@ -67,7 +67,6 @@ import { VersionControlService, ViewerGroup, ViewerSessionResponse, - ResetThumbRequest, } from "./explorer.ts"; import { AppError, Code, CrHeaders, defaultOpts, send, ThunkResponse } from "./request.ts"; import { CreateDavAccountService, DavAccount, ListDavAccountsResponse, ListDavAccountsService } from "./setting.ts"; @@ -293,23 +292,6 @@ export function getFileThumb(path: string, contextHint?: string): ThunkResponse< }; } -export function sendResetFileThumbs(req: ResetThumbRequest): ThunkResponse { - return async (dispatch, _getState) => { - return await dispatch( - send( - "/file/thumb/reset", - { - data: req, - method: "POST", - }, - { - ...defaultOpts, - }, - ), - ); - }; -} - // Thin wrapper to query supported thumbnail extensions from backend export function getThumbExts(): ThunkResponse<{ thumb_exts?: string[] }> { return async (dispatch, _getState) => { diff --git a/src/api/explorer.ts b/src/api/explorer.ts index b7e22c5..65a6fb6 100644 --- a/src/api/explorer.ts +++ b/src/api/explorer.ts @@ -217,11 +217,6 @@ export interface FileThumbResponse { expires?: string; } -// Request body for resetting thumbnails for given file URIs -export interface ResetThumbRequest { - uris: string[]; -} - export interface DeleteFileService { uris: string[]; unlink?: boolean; diff --git a/src/component/FileManager/Explorer/GalleryView/GalleryImage.tsx b/src/component/FileManager/Explorer/GalleryView/GalleryImage.tsx index 7a87a4f..c20ca12 100644 --- a/src/component/FileManager/Explorer/GalleryView/GalleryImage.tsx +++ b/src/component/FileManager/Explorer/GalleryView/GalleryImage.tsx @@ -93,8 +93,11 @@ const GalleryImage = memo((props: FileBlockProps) => { return; } + // Reset to loading state before reloading thumb (e.g., after reset) + setImageLoading(true); + setThumbSrc(undefined); tryLoadThumbSrc(); - }, [inView]); + }, [inView, file, file.metadata?.[Metadata.thumbDisabled]]); const onIconClick = useCallback( (e: React.MouseEvent) => { diff --git a/src/component/FileManager/Explorer/GridView/GridFile.tsx b/src/component/FileManager/Explorer/GridView/GridFile.tsx index 8679b90..57e7e5b 100644 --- a/src/component/FileManager/Explorer/GridView/GridFile.tsx +++ b/src/component/FileManager/Explorer/GridView/GridFile.tsx @@ -328,8 +328,11 @@ const GridFile = memo((props: FileBlockProps) => { return; } + // Reset to loading state before reloading thumb (e.g., after reset) + setImageLoading(true); + setThumbSrc(undefined); tryLoadThumbSrc(); - }, [inView]); + }, [inView, file, file.metadata?.[Metadata.thumbDisabled]]); const hoverProps = bindDelayedHover(popupState, 800); const { open: thumbPopoverOpen, ...rest } = bindPopover(popupState); diff --git a/src/redux/thunks/file.ts b/src/redux/thunks/file.ts index d8ca74c..43ce170 100644 --- a/src/redux/thunks/file.ts +++ b/src/redux/thunks/file.ts @@ -6,7 +6,6 @@ import { getFileEntityUrl, getFileList, getFileThumb, - sendResetFileThumbs, sendCreateFile, sendDeleteFiles, sendMetadataPatch, @@ -1157,7 +1156,7 @@ export function batchGetDirectLinks(index: number, files: FileResponse[]): AppTh } export function resetThumbnails(files: FileResponse[]): AppThunk { - return async (dispatch, _getState) => { + return async (dispatch, getState) => { const cache = getCachedThumbExts(); const uris = files .filter((f) => f.type == FileType.file) @@ -1177,41 +1176,39 @@ export function resetThumbnails(files: FileResponse[]): AppThunk { } try { + // Re-enable thumbnails by removing the disable mark, and update local metadata/cache. + const targetFiles = files + .filter((f) => f.type == FileType.file) + .filter((f) => + cache === undefined || cache === null ? true : cache.has((fileExtension(f.name) || "").toLowerCase()), + ); + await dispatch( - sendResetFileThumbs({ - uris, - }), + patchFileMetadata(FileManagerIndex.main, targetFiles, [ + { + key: Metadata.thumbDisabled, + remove: true, + }, + ]), ); + // 预取:立即为所选文件请求缩略图(不依赖列表刷新或滚动触发) + const fm = getState().fileManager[FileManagerIndex.main]; + const toPrefetch = targetFiles + .map((f) => fm.list?.files.find((ff) => ff.path === f.path) || f) + .filter((f): f is FileResponse => !!f); + // 并发触发 GET /file/thumb + await Promise.allSettled(toPrefetch.map((f) => dispatch(loadFileThumb(FileManagerIndex.main, f)))); + + // 成功信息 enqueueSnackbar({ message: i18next.t("application:fileManager.resetThumbnailRequested"), variant: "success", action: DefaultCloseAction, }); + // 不再刷新文件列表;组件会基于metadata变化自动重新请求所选文件的缩略图 } catch (_e) { // Error snackbar is handled in send() - } finally { - // Clear cached thumbnails so they will be reloaded next time - files - .filter((f) => f.type == FileType.file) - .forEach((f) => - dispatch( - fileUpdated({ - index: 0, - value: [ - { - file: f, - oldPath: f.path, - }, - ], - }), - ), - ); - - // Use the same refresh approach as uploader: refresh after a short delay - setTimeout(() => { - dispatch(refreshFileList(0)); - }, 1000); } }; }