fix: four more correctness bugs from PR review

- Duplicate scanner now emits one DuplicateGroup per distinct full hash
  within a sample-hash bucket, preventing disjoint sets (A,A vs B,B)
  from being merged and presented as a single deletable group
- Tagger model download now installs the shared ONNX runtime DLLs via
  ensure_onnx_runtime so the tagger is ready on a clean install without
  requiring the caption model to have been downloaded first
- Caption queue clear now follows the tagging worker pattern: marks
  in-flight rows as cancelled and deletes only non-processing rows;
  the caption worker skips writing results for cancelled jobs; startup
  cleanup removes any leftover cancelled caption rows
- Region search pagination now stores the crop rect in state and uses
  find_similar_by_region for subsequent pages instead of falling through
  to loadImages which appended unrelated folder results
This commit is contained in:
2026-06-06 22:00:20 +01:00
parent f82002129a
commit de0c2ab12d
5 changed files with 91 additions and 31 deletions
+27 -1
View File
@@ -238,6 +238,7 @@ interface GalleryState {
similarHasMore: boolean;
similarScope: SimilarScope;
similarFolderId: number | null;
similarCrop: { x: number; y: number; w: number; h: number } | null;
galleryScrollResetKey: number;
activeView: ActiveView;
exploreMode: ExploreMode;
@@ -567,6 +568,7 @@ export const useGalleryStore = create<GalleryState>((set, get) => ({
similarHasMore: false,
similarScope: "all_media",
similarFolderId: null,
similarCrop: null,
galleryScrollResetKey: 0,
activeView: "gallery",
exploreMode: "visual",
@@ -771,7 +773,7 @@ export const useGalleryStore = create<GalleryState>((set, get) => ({
},
loadMoreImages: async () => {
const { loadedCount, totalImages, loadingImages, collectionTitle, similarSourceImageId, similarHasMore, similarFolderId } = get();
const { loadedCount, totalImages, loadingImages, collectionTitle, similarSourceImageId, similarHasMore, similarFolderId, similarCrop } = get();
if (loadingImages || loadedCount >= totalImages) return;
if (collectionTitle === "Explore Cluster") return;
if (collectionTitle === "Similar Images" && similarSourceImageId !== null) {
@@ -779,6 +781,28 @@ export const useGalleryStore = create<GalleryState>((set, get) => ({
await get().loadSimilarImages(similarSourceImageId, similarFolderId, false);
return;
}
if (collectionTitle === "Region Search Results" && similarSourceImageId !== null && similarCrop !== null) {
if (!similarHasMore) return;
const result = await invoke<SimilarImagesPage>("find_similar_by_region", {
params: {
image_id: similarSourceImageId,
crop_x: similarCrop.x,
crop_y: similarCrop.y,
crop_w: similarCrop.w,
crop_h: similarCrop.h,
folder_id: similarFolderId,
offset: loadedCount,
limit: PAGE_SIZE,
},
});
set((state) => ({
images: [...state.images, ...result.images],
loadedCount: state.loadedCount + result.images.length,
totalImages: result.has_more ? state.loadedCount + result.images.length + 1 : state.loadedCount + result.images.length,
similarHasMore: result.has_more,
}));
return;
}
await get().loadImages(false);
},
@@ -1006,6 +1030,7 @@ export const useGalleryStore = create<GalleryState>((set, get) => ({
similarSourceImageId: imageId,
similarSourceFolderId: sourceFolderId,
similarFolderId: folderId ?? null,
similarCrop: crop,
similarScope,
galleryScrollResetKey: state.galleryScrollResetKey + 1,
selectedImage: null,
@@ -1038,6 +1063,7 @@ export const useGalleryStore = create<GalleryState>((set, get) => ({
similarSourceFolderId: sourceFolderId,
similarHasMore: result.has_more,
similarFolderId: folderId ?? null,
similarCrop: crop,
similarScope,
});
} catch (error) {