Skip to content

Commit 0afc052

Browse files
committed
chore(View Album > useSearch): Bookmark anchors you in your current filtered view, while Clear anchors you to the photo while blowing away the filters.
1 parent 69e7147 commit 0afc052

File tree

7 files changed

+54
-38
lines changed

7 files changed

+54
-38
lines changed

src/components/Album/AlbumClient.tsx

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,10 @@ function AlbumClient({ items = [], meta, indexedKeywords, clusteredMarkers }: Al
4040

4141
useEffect(() => {
4242
if (!selectId || itemsToShow.length === 0) return
43-
let idx = itemsToShow.findIndex(i => i.id === selectId)
44-
45-
// Fallback: try matching by filename (for All view where IDs may not be unique)
46-
if (idx < 0) {
47-
idx = itemsToShow.findIndex(i => {
48-
const filename = Array.isArray(i.filename) ? i.filename[0] : i.filename
49-
return filename === selectId
50-
})
51-
}
43+
const idx = itemsToShow.findIndex(i => {
44+
const filename = Array.isArray(i.filename) ? i.filename[0] : i.filename
45+
return filename === selectId
46+
})
5247

5348
// Only slide if we found the item (idx >= 0) AND the gallery isn't already at that index
5449
if (idx >= 0 && refImageGallery.current?.getCurrentIndex?.() !== idx) {

src/components/All/AllClient.tsx

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,22 @@ export default function AllClient({ items, indexedKeywords, clusteredMarkers }:
3535
// Handle URL ?select= parameter
3636
useEffect(() => {
3737
if (!selectId || itemsToShow.length === 0) return
38-
let idx = itemsToShow.findIndex(i => i.id === selectId)
3938

40-
// Fallback: try matching by filename
41-
if (idx < 0) {
42-
idx = itemsToShow.findIndex(i => {
43-
const filename = Array.isArray(i.filename) ? i.filename[0] : i.filename
44-
return filename === selectId
45-
})
46-
}
39+
const idx = itemsToShow.findIndex(i => {
40+
const filename = Array.isArray(i.filename) ? i.filename[0] : i.filename
41+
return filename === selectId
42+
})
4743

48-
// Only slide if found and not already at that index
49-
if (idx >= 0 && refImageGallery.current?.getCurrentIndex?.() !== idx) {
50-
refImageGallery.current?.slideToIndex(idx)
51-
setMemoryIndex(idx)
52-
setViewed(idx)
44+
if (idx >= 0) {
45+
// Use timeout to allow gallery to process items update (which might reset index)
46+
// before enforcing the selected index
47+
setTimeout(() => {
48+
if (refImageGallery.current?.getCurrentIndex?.() !== idx) {
49+
refImageGallery.current?.slideToIndex(idx)
50+
setMemoryIndex(idx)
51+
setViewed(idx)
52+
}
53+
}, 0)
5354
}
5455
}, [selectId, itemsToShow, refImageGallery, setMemoryIndex, setViewed])
5556

src/components/All/Items.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ function All({ items, keyword, refImageGallery }: InputProps) {
2424
{items.map((item, index) => (
2525
<li key={item.filename.toString()}>
2626
<b className={styles.albumName}>{item.album}</b>
27-
<Link href={`/${item.gallery}/${item.album}?select=${item.id}`} title={item.corpus}>
27+
<Link href={`/${item.gallery}/${item.album}?select=${Array.isArray(item.filename) ? item.filename[0] : item.filename}`} title={item.corpus}>
2828
{!showThumbnail(keyword) && item.caption}
2929
{showThumbnail(keyword) && <Img src={item.thumbPath} alt={item.caption} title={item.corpus} width={width} height={height} />}
3030
</Link>

src/components/Persons/PersonsClient.tsx

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,20 @@ export default function PersonsClient({
4141
// Handle URL ?select= parameter
4242
useEffect(() => {
4343
if (!selectId || ageFiltered.length === 0) return
44-
let idx = ageFiltered.findIndex(i => i.id === selectId)
4544

46-
// Fallback: try matching by filename
47-
if (idx < 0) {
48-
idx = ageFiltered.findIndex(i => {
49-
const filename = Array.isArray(i.filename) ? i.filename[0] : i.filename
50-
return filename === selectId
51-
})
52-
}
45+
const idx = ageFiltered.findIndex(i => {
46+
const filename = Array.isArray(i.filename) ? i.filename[0] : i.filename
47+
return filename === selectId
48+
})
5349

54-
// Only slide if found and not already at that index
55-
if (idx >= 0 && refImageGallery.current?.getCurrentIndex?.() !== idx) {
56-
refImageGallery.current?.slideToIndex(idx)
57-
setMemoryIndex(idx)
58-
setViewed(idx)
50+
if (idx >= 0) {
51+
setTimeout(() => {
52+
if (refImageGallery.current?.getCurrentIndex?.() !== idx) {
53+
refImageGallery.current?.slideToIndex(idx)
54+
setMemoryIndex(idx)
55+
setViewed(idx)
56+
}
57+
}, 0)
5958
}
6059
}, [selectId, ageFiltered, refImageGallery, setMemoryIndex, setViewed])
6160

src/hooks/useBookmark.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,31 @@
11
'use client'
22

33
import { Button } from '@mui/joy'
4+
import { useRouter } from 'next/navigation'
45
import type { RefObject } from 'react'
56

67
interface UseBookmarkProps<ItemType> {
78
refImageGallery?: RefObject<any>
89
displayedItems: ItemType[]
910
pathname: string
11+
currentIndex?: number
12+
selectById?: (id: string) => void
1013
}
1114

1215
export default function useBookmark<ItemType>({
1316
refImageGallery,
1417
displayedItems,
1518
pathname,
19+
currentIndex,
20+
selectById,
1621
}: UseBookmarkProps<ItemType>) {
22+
const router = useRouter()
23+
1724
const handleBookmark = () => {
1825
// Get current photo ID from displayed items (respects map filter)
19-
const currentIndex = refImageGallery?.current?.getCurrentIndex?.() ?? 0
20-
const currentItem = displayedItems[currentIndex]
26+
const galleryIndex = refImageGallery?.current?.getCurrentIndex?.()
27+
const indexToUse = typeof galleryIndex === 'number' ? galleryIndex : (currentIndex ?? 0)
28+
const currentItem = displayedItems[indexToUse]
2129
if (!currentItem) return
2230

2331
// Use filename as unique identifier (works across all albums)
@@ -26,9 +34,17 @@ export default function useBookmark<ItemType>({
2634
: (currentItem as any).filename
2735
if (!identifier) return
2836

37+
// Notify parent to track selection (updates memoryIndex to match ID)
38+
if (selectById) {
39+
selectById(identifier)
40+
}
41+
2942
// Copy bookmark URL to clipboard
3043
const bookmarkUrl = `${window.location.origin}${pathname}?select=${identifier}`
3144
navigator.clipboard.writeText(bookmarkUrl)
45+
46+
// Update URL to reflect the selection
47+
router.replace(`${pathname}?select=${identifier}`, { scroll: false })
3248
}
3349

3450
const BookmarkButton = () => (

src/hooks/useMapFilter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ export default function useMapFilter({ items, indexedKeywords }: All.ItemData) {
5050
setDisplayedItems,
5151
} = useSearch({
5252
items,
53+
memoryIndex,
5354
setMemoryIndex,
5455
indexedKeywords,
5556
refImageGallery,

src/hooks/useSearch.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface ServerSideItem {
1919

2020
interface UseSearchProps<ItemType> {
2121
items: ItemType[];
22+
memoryIndex?: number;
2223
setMemoryIndex?: Dispatch<SetStateAction<number>>;
2324
indexedKeywords?: IndexedKeywords[];
2425
refImageGallery?: React.RefObject<any>;
@@ -29,6 +30,7 @@ interface UseSearchProps<ItemType> {
2930

3031
export default function useSearch<ItemType extends ServerSideItem>({
3132
items,
33+
memoryIndex,
3234
setMemoryIndex,
3335
indexedKeywords = [],
3436
refImageGallery,
@@ -116,6 +118,8 @@ export default function useSearch<ItemType extends ServerSideItem>({
116118
refImageGallery,
117119
displayedItems: displayedItems || filtered,
118120
pathname,
121+
currentIndex: memoryIndex,
122+
selectById,
119123
})
120124

121125
const keywordResultLabel = keyword ? <> for &quot;{keyword}&quot;</> : null

0 commit comments

Comments
 (0)