Order carousel as images appear in items / markdown (#2239)
* carousel sort in deterministic order * imgIndex 0 for ItemEmbed * fix order for item-full * fix indexing in ItemEmbed * Revert "fix indexing in ItemEmbed" This reverts commit f7863af30a1a02b189bfc79237606851c4da1abf. * Revert "fix order for item-full" This reverts commit 489e25ea82056bd83a818e581eb2bbfcf947e401. * Revert "imgIndex 0 for ItemEmbed" This reverts commit cd5fff1bae151e44db717f2a2173f673793bc6d0. * carousel preserves ordering rendered on screen * reorder carousel when sort changes * fix cursor detected bugs * register media to carousel before image load, confirm afterwards * Remove unnecessary ref from dependencies * Add missing dependencies * Add missing dependencies * Check if src was found in Carousel --------- Co-authored-by: ekzyis <ek@stacker.news>
This commit is contained in:
parent
af77985b38
commit
97cbfec38e
@ -56,8 +56,9 @@ function useArrowKeys ({ moveLeft, moveRight }) {
|
||||
function Carousel ({ close, mediaArr, src, setOptions }) {
|
||||
const [index, setIndex] = useState(mediaArr.findIndex(([key]) => key === src))
|
||||
const [currentSrc, canGoLeft, canGoRight] = useMemo(() => {
|
||||
if (index === -1) return [src, false, false]
|
||||
return [mediaArr[index][0], index > 0, index < mediaArr.length - 1]
|
||||
}, [mediaArr, index])
|
||||
}, [src, mediaArr, index])
|
||||
|
||||
useEffect(() => {
|
||||
if (index === -1) return
|
||||
@ -115,8 +116,12 @@ export function CarouselProvider ({ children }) {
|
||||
const showModal = useShowModal()
|
||||
|
||||
const showCarousel = useCallback(({ src }) => {
|
||||
// only show confirmed entries
|
||||
const confirmedEntries = Array.from(media.current.entries())
|
||||
.filter(([, entry]) => entry.confirmed)
|
||||
|
||||
showModal((close, setOptions) => {
|
||||
return <Carousel close={close} mediaArr={Array.from(media.current.entries())} src={src} setOptions={setOptions} />
|
||||
return <Carousel close={close} mediaArr={confirmedEntries} src={src} setOptions={setOptions} />
|
||||
}, {
|
||||
fullScreen: true,
|
||||
overflow: <CarouselOverflow {...media.current.get(src)} />
|
||||
@ -124,14 +129,25 @@ export function CarouselProvider ({ children }) {
|
||||
}, [showModal])
|
||||
|
||||
const addMedia = useCallback(({ src, originalSrc, rel }) => {
|
||||
media.current.set(src, { src, originalSrc, rel })
|
||||
media.current.set(src, { src, originalSrc, rel, confirmed: false })
|
||||
}, [])
|
||||
|
||||
const confirmMedia = useCallback((src) => {
|
||||
const mediaItem = media.current.get(src)
|
||||
if (mediaItem) {
|
||||
mediaItem.confirmed = true
|
||||
media.current.set(src, mediaItem)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const removeMedia = useCallback((src) => {
|
||||
media.current.delete(src)
|
||||
}, [])
|
||||
|
||||
const value = useMemo(() => ({ showCarousel, addMedia, removeMedia }), [showCarousel, addMedia, removeMedia])
|
||||
const value = useMemo(
|
||||
() => ({ showCarousel, addMedia, confirmMedia, removeMedia }),
|
||||
[showCarousel, addMedia, confirmMedia, removeMedia]
|
||||
)
|
||||
return <CarouselContext.Provider value={value}>{children}</CarouselContext.Provider>
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@ import { UNKNOWN_LINK_REL } from '@/lib/constants'
|
||||
import classNames from 'classnames'
|
||||
import { CarouselProvider } from './carousel'
|
||||
import Embed from './embed'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
function BioItem ({ item, handleClick }) {
|
||||
const { me } = useMe()
|
||||
@ -165,6 +166,9 @@ export default function ItemFull ({ item, fetchMoreComments, bio, rank, ...props
|
||||
commentsViewed(item)
|
||||
}, [item.lastCommentAt])
|
||||
|
||||
const router = useRouter()
|
||||
const carouselKey = `${item.id}-${router.query?.sort || 'default'}`
|
||||
|
||||
return (
|
||||
<>
|
||||
{rank
|
||||
@ -174,7 +178,7 @@ export default function ItemFull ({ item, fetchMoreComments, bio, rank, ...props
|
||||
</div>)
|
||||
: <div />}
|
||||
<RootProvider root={item.root || item}>
|
||||
<CarouselProvider key={item.id}>
|
||||
<CarouselProvider key={carouselKey}>
|
||||
{item.parentId
|
||||
? <Comment topLevel item={item} replyOpen includeParent noComments {...props} />
|
||||
: (
|
||||
|
@ -75,12 +75,19 @@ const Media = memo(function Media ({
|
||||
export default function MediaOrLink ({ linkFallback = true, ...props }) {
|
||||
const media = useMediaHelper(props)
|
||||
const [error, setError] = useState(false)
|
||||
const { showCarousel, addMedia, removeMedia } = useCarousel()
|
||||
const { showCarousel, addMedia, confirmMedia, removeMedia } = useCarousel()
|
||||
|
||||
// register placeholder immediately on mount if we have a src
|
||||
useEffect(() => {
|
||||
if (!media.bestResSrc) return
|
||||
addMedia({ src: media.bestResSrc, originalSrc: media.originalSrc, rel: props.rel })
|
||||
}, [addMedia, media.bestResSrc, media.originalSrc, props.rel])
|
||||
|
||||
// confirm media for carousel based on image detection
|
||||
useEffect(() => {
|
||||
if (!media.image) return
|
||||
addMedia({ src: media.bestResSrc, originalSrc: media.originalSrc, rel: props.rel })
|
||||
}, [media.image])
|
||||
confirmMedia(media.bestResSrc)
|
||||
}, [confirmMedia, media.image, media.bestResSrc])
|
||||
|
||||
const handleClick = useCallback(() => showCarousel({ src: media.bestResSrc }),
|
||||
[showCarousel, media.bestResSrc])
|
||||
|
Loading…
x
Reference in New Issue
Block a user