<commit_before>import { color, Flex, space, Spacer } from "@artsy/palette"
import { ImageCarousel_images } from "__generated__/ImageCarousel_images.graphql"
import { devCacheBust } from "lib/utils/devCacheBust"
import React, { useCallback, useEffect, useMemo, useState } from "react"
import { Animated, Dimensions, FlatList, NativeScrollEvent, NativeSyntheticEvent } from "react-native"
import { createFragmentContainer, graphql } from "react-relay"
import { findClosestIndex, getMeasurements } from "./geometry"
import { ImageWithLoadingState } from "./ImageWithLoadingState"

export interface ImageCarouselProps {
  images: ImageCarousel_images
}

const windowWidth = Dimensions.get("window").width
// The logic for cardHeight comes from the zeplin spec https://zpl.io/25JLX0Q
const cardHeight = windowWidth >= 375 ? 340 : 290
export const cardBoundingBox = { width: windowWidth, height: cardHeight }

export const ImageCarousel: React.FC<ImageCarouselProps> = ({ images }) => {
  const measurements = useMemo(() => getMeasurements({ images, boundingBox: cardBoundingBox }), [images])
  const offsets = useMemo(() => measurements.map(m => m.cumulativeScrollOffset), [measurements])

  const [imageIndex, setImageIndex] = useState(0)

  // update the imageIndex on scroll
  const onScroll = useCallback(
    (e: NativeSyntheticEvent<NativeScrollEvent>) => {
      // This finds the index of the image which is being given the most
      // screen real estate at any given point in time.
      setImageIndex(findClosestIndex(offsets, e.nativeEvent.contentOffset.x))
    },
    [setImageIndex, offsets]
  )

  return (
    <Flex>
      <FlatList<ImageCarousel_images[number]>
        data={images}
        horizontal
        showsHorizontalScrollIndicator={false}
        scrollEnabled={images.length > 1}
        snapToOffsets={offsets}
        keyExtractor={item => item.url}
        decelerationRate="fast"
        onScroll={onScroll}
        renderItem={({ item, index }) => {<commit_msg>add comment about implicit reliance on window size<commit_after>import { color, Flex, space, Spacer } from "@artsy/palette"
import { ImageCarousel_images } from "__generated__/ImageCarousel_images.graphql"
import { devCacheBust } from "lib/utils/devCacheBust"
import React, { useCallback, useEffect, useMemo, useState } from "react"
import { Animated, Dimensions, FlatList, NativeScrollEvent, NativeSyntheticEvent } from "react-native"
import { createFragmentContainer, graphql } from "react-relay"
import { findClosestIndex, getMeasurements } from "./geometry"
import { ImageWithLoadingState } from "./ImageWithLoadingState"

export interface ImageCarouselProps {
  images: ImageCarousel_images
}

const windowWidth = Dimensions.get("window").width
// The logic for cardHeight comes from the zeplin spec https://zpl.io/25JLX0Q
const cardHeight = windowWidth >= 375 ? 340 : 290
export const cardBoundingBox = { width: windowWidth, height: cardHeight }

/**
 * ImageCarousel
 * NOTE: This component currently assumes it is being rendered at the full width of the screen.
 * To use it in places where this is not desirable it would need to take explicit width and height props
 * and use those to calculate a dynamic version of cardBoundingBox and perhaps other geometric quantities.
 */
export const ImageCarousel: React.FC<ImageCarouselProps> = ({ images }) => {
  const measurements = useMemo(() => getMeasurements({ images, boundingBox: cardBoundingBox }), [images])
  const offsets = useMemo(() => measurements.map(m => m.cumulativeScrollOffset), [measurements])

  const [imageIndex, setImageIndex] = useState(0)

  // update the imageIndex on scroll
  const onScroll = useCallback(
    (e: NativeSyntheticEvent<NativeScrollEvent>) => {
      // This finds the index of the image which is being given the most
      // screen real estate at any given point in time.
      setImageIndex(findClosestIndex(offsets, e.nativeEvent.contentOffset.x))
    },
    [setImageIndex, offsets]
  )

  return (
    <Flex>
      <FlatList<ImageCarousel_images[number]>
        data={images}
        horizontal
        showsHorizontalScrollIndicator={false}
        scrollEnabled={images.length > 1}
        snapToOffsets={offsets}
        keyExtractor={item => item.url}
        decelerationRate="fast"
        onScroll={onScroll}
        renderItem={({ item, index }) => {
{'fraction_non_alphanumeric': 0.10064338235294118, 'fraction_numerical': 0.006433823529411764, 'mean_word_length': 4.328029375764994, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 29, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4507671', 'n_tokens_mistral': 1248, 'n_tokens_neox': 1209, 'n_words': 361}