fix: heap convert dialog supports nested subfolders + visiblePhotoIds loop guard
- HeapConvertDialog: switch the target picker from sourceFolders.list (top-level source roots only) to useFolderTreeQuery, flattened depth-first into a list with depth info. Each option is indented with non-breaking spaces so nested subfolders read as a tree in the native dropdown. Backend already accepts any Folder id, so no server change needed. - photoStore.setVisiblePhotoIds: short-circuit when the new id list matches the existing one element-for-element. Avoids feedback loops if a publisher fires from an effect on a render where the contents haven't actually changed (which was triggering React error #185). - Timeline: pull setVisiblePhotoIds via a focused selector instead of the wholesale destructure so the publisher subscription doesn't re-render Timeline on unrelated photo store changes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -81,7 +81,23 @@ export const usePhotoStore = create<PhotoStore>((set) => ({
|
||||
|
||||
setViewMode: (mode) => set({ viewMode: mode }),
|
||||
|
||||
setVisiblePhotoIds: (visiblePhotoIds) => set({ visiblePhotoIds }),
|
||||
// No-op when the content is identical so callers can fire from an
|
||||
// effect without risking a re-render loop.
|
||||
setVisiblePhotoIds: (visiblePhotoIds) =>
|
||||
set((s) => {
|
||||
const prev = s.visiblePhotoIds
|
||||
if (prev.length === visiblePhotoIds.length) {
|
||||
let same = true
|
||||
for (let i = 0; i < prev.length; i++) {
|
||||
if (prev[i] !== visiblePhotoIds[i]) {
|
||||
same = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if (same) return s
|
||||
}
|
||||
return { visiblePhotoIds }
|
||||
}),
|
||||
|
||||
openPreview: (id) => set({ viewMode: 'preview', activePhotoId: id }),
|
||||
|
||||
|
||||
Reference in New Issue
Block a user