<commit_before>import { Flex } from "@artsy/palette"
import { ArtworkGrid_artworks } from "__generated__/ArtworkGrid_artworks.graphql"
import { Mediator } from "Artsy"
import { ArtworkGridEmptyState } from "Components/ArtworkGrid/ArtworkGridEmptyState"
import { isEqual } from "lodash"
import memoizeOnce from "memoize-one"
import React, { ReactNode } from "react"
import ReactDOM from "react-dom"
// @ts-ignore
import { ComponentRef, createFragmentContainer, graphql } from "react-relay"
// @ts-ignore
import styled, { StyledComponentClass } from "styled-components"
import { Media, valuesWithBreakpointProps } from "Utils/Responsive"
import GridItem from "../Artwork/GridItem"

type SectionedArtworks = Array<Array<ArtworkGrid_artworks["edges"][0]["node"]>>

type Artwork = ArtworkGrid_artworks["edges"][0]["node"]

export interface ArtworkGridProps
  extends React.HTMLProps<ArtworkGridContainer> {
  artworks: ArtworkGrid_artworks
  columnCount?: number | number[]
  preloadImageCount?: number
  itemMargin?: number
  mediator?: Mediator
  onBrickClick?: (artwork?: Artwork) => void
  onClearFilters?: () => any
  onLoadMore?: () => any
  sectionMargin?: number
  user?: User
  emptyStateComponent?: ReactNode | boolean
}

export interface ArtworkGridContainerState {
  loading: boolean
  interval: any
}

export class ArtworkGridContainer extends React.Component<
  ArtworkGridProps,
  ArtworkGridContainerState
> {
  static defaultProps = {
    columnCount: [3],
    sectionMargin: 20,
    itemMargin: 20,
    preloadImageCount: 6,
  }

  state = {
    interval: null,
    loading: false,
  }

  private get _columnCount(): number[] {
    const columnCount = this.props.columnCount
    return typeof columnCount === "number" ? [columnCount] : columnCount
  }

  componentDidMount() {
    if (this.props.onLoadMore) {
      const interval = setInterval(() => {
        this.maybeLoadMore()
      }, 150)
      this.setState({ interval })
    }
  }

  componentWillUnmount() {
    if (this.state.interval) {
      clearInterval(this.state.interval)
    }
  }

  columnBreakpointProps = memoizeOnce(
    (columnCount: number[]) => valuesWithBreakpointProps(columnCount),
    isEqual
  )

  // TODO: This will still re-calculate column layout from scratch when new
  //       artworks are added (paginated). Ideally it would just continue
  //       calculations from where it finished last time.
  sectionedArtworksForAllBreakpoints: (
    artworks: ArtworkGrid_artworks,
    columnCount: number[]
  ) => SectionedArtworks[] = memoizeOnce(
    (artworks, columnCount) =>
      columnCount.map(n => createSectionedArtworks(artworks, n)),
    areSectionedArtworksEqual
  )

  maybeLoadMore() {
    const threshold = window.innerHeight + window.scrollY
    const el = ReactDOM.findDOMNode(this) as Element
    if (threshold >= el.clientHeight + el.scrollTop) {
      this.props.onLoadMore()
    }
  }

  renderSectionsForSingleBreakpoint(
    columnCount: number,
    sectionedArtworks: SectionedArtworks
  ) {
    const { preloadImageCount } = this.props
    const spacerStyle = {
      height: this.props.itemMargin,
    }
    const sections = []

    for (let i = 0; i < columnCount; i++) {
      const artworkComponents = []
      for (let j = 0; j < sectionedArtworks[i].length; j++) {
        const artwork = sectionedArtworks[i][j]
        artworkComponents.push(
          <GridItem
            artwork={artwork}
            key={artwork.id}
            mediator={this.props.mediator}
            lazyLoad={i * columnCount + j >= preloadImageCount}
            onClick={() => {
              if (this.props.onBrickClick) {
                this.props.onBrickClick(artwork)
              }
            }}
          />
        )
        // Setting a marginBottom on the artwork component didn’t work, so using a spacer view instead.
        if (j < sectionedArtworks[i].length - 1) {
          artworkComponents.push(
            <div style={spacerStyle} key={"spacer-" + j + "-" + artwork.id} />
          )
        }
      }

      const sectionSpecificStyle = {
        flex: 1,
        minWidth: 0,
        marginRight: i === columnCount - 1 ? 0 : this.props.sectionMargin,
      }

      sections.push(
        <div style={sectionSpecificStyle} key={i}>
          {artworkComponents}
        </div>
      )
    }
    return sections
  }

  renderSectionsForAllBreakpoints() {
    const columnCount = this._columnCount

    // Only 1 column ever, so no need to wrap.
    if (this._columnCount.length === 1) {
      return this.renderSectionsForSingleBreakpoint(
        columnCount[0],
        this.sectionedArtworksForAllBreakpoints(
          this.props.artworks,
          columnCount<commit_msg>Update variables for clairty, fix math (again)<commit_after>import { Flex } from "@artsy/palette"
import { ArtworkGrid_artworks } from "__generated__/ArtworkGrid_artworks.graphql"
import { Mediator } from "Artsy"
import { ArtworkGridEmptyState } from "Components/ArtworkGrid/ArtworkGridEmptyState"
import { isEqual } from "lodash"
import memoizeOnce from "memoize-one"
import React, { ReactNode } from "react"
import ReactDOM from "react-dom"
// @ts-ignore
import { ComponentRef, createFragmentContainer, graphql } from "react-relay"
// @ts-ignore
import styled, { StyledComponentClass } from "styled-components"
import { Media, valuesWithBreakpointProps } from "Utils/Responsive"
import GridItem from "../Artwork/GridItem"

type SectionedArtworks = Array<Array<ArtworkGrid_artworks["edges"][0]["node"]>>

type Artwork = ArtworkGrid_artworks["edges"][0]["node"]

export interface ArtworkGridProps
  extends React.HTMLProps<ArtworkGridContainer> {
  artworks: ArtworkGrid_artworks
  columnCount?: number | number[]
  preloadImageCount?: number
  itemMargin?: number
  mediator?: Mediator
  onBrickClick?: (artwork?: Artwork) => void
  onClearFilters?: () => any
  onLoadMore?: () => any
  sectionMargin?: number
  user?: User
  emptyStateComponent?: ReactNode | boolean
}

export interface ArtworkGridContainerState {
  loading: boolean
  interval: any
}

export class ArtworkGridContainer extends React.Component<
  ArtworkGridProps,
  ArtworkGridContainerState
> {
  static defaultProps = {
    columnCount: [3],
    sectionMargin: 20,
    itemMargin: 20,
    preloadImageCount: 6,
  }

  state = {
    interval: null,
    loading: false,
  }

  private get _columnCount(): number[] {
    const columnCount = this.props.columnCount
    return typeof columnCount === "number" ? [columnCount] : columnCount
  }

  componentDidMount() {
    if (this.props.onLoadMore) {
      const interval = setInterval(() => {
        this.maybeLoadMore()
      }, 150)
      this.setState({ interval })
    }
  }

  componentWillUnmount() {
    if (this.state.interval) {
      clearInterval(this.state.interval)
    }
  }

  columnBreakpointProps = memoizeOnce(
    (columnCount: number[]) => valuesWithBreakpointProps(columnCount),
    isEqual
  )

  // TODO: This will still re-calculate column layout from scratch when new
  //       artworks are added (paginated). Ideally it would just continue
  //       calculations from where it finished last time.
  sectionedArtworksForAllBreakpoints: (
    artworks: ArtworkGrid_artworks,
    columnCount: number[]
  ) => SectionedArtworks[] = memoizeOnce(
    (artworks, columnCount) =>
      columnCount.map(n => createSectionedArtworks(artworks, n)),
    areSectionedArtworksEqual
  )

  maybeLoadMore() {
    const threshold = window.innerHeight + window.scrollY
    const el = ReactDOM.findDOMNode(this) as Element
    if (threshold >= el.clientHeight + el.scrollTop) {
      this.props.onLoadMore()
    }
  }

  renderSectionsForSingleBreakpoint(
    columnCount: number,
    sectionedArtworks: SectionedArtworks
  ) {
    const { preloadImageCount } = this.props
    const spacerStyle = {
      height: this.props.itemMargin,
    }
    const sections = []

    for (let column = 0; column < columnCount; column++) {
      const artworkComponents = []
      for (let row = 0; row < sectionedArtworks[column].length; row++) {
        /**
         * The position of the image in the grid represented
         * by counting left to right, top to bottom.
         *
         * Here's a stackoverflow explaining the math: https://stackoverflow.com/questions/1730961/convert-a-2d-array-index-into-a-1d-index
         */
        const artworkIndex = column * columnCount + row

        const artwork = sectionedArtworks[column][row]
        artworkComponents.push(
          <GridItem
            artwork={artwork}
            key={artwork.id}
            mediator={this.props.mediator}
            lazyLoad={artworkIndex >= preloadImageCount}
            onClick={() => {
              if (this.props.onBrickClick) {
                this.props.onBrickClick(artwork)
              }
            }}
          />
        )
        // Setting a marginBottom on the artwork component didn’t work, so using a spacer view instead.
        if (row < sectionedArtworks[column].length - 1) {
          artworkComponents.push(
            <div style={spacerStyle} key={"spacer-" + row + "-" + artwork.id} />
          )
        }
      }

      const sectionSpecificStyle = {
        flex: 1,
        minWidth: 0,
        marginRight: column === columnCount - 1 ? 0 : this.props.sectionMargin,
      }

      sections.push(
        <div style={sectionSpecificStyle} key={column}>
          {artworkComponents}
        </div>
      )
    }
    return sections
  }

  renderSectionsForAllBreakpoints() {
    const columnCount = this._columnCount

    // Only 1 column ever, so no need to wrap.
    if (this._columnCount.length === 1) {
      return this.renderSectionsForSingleBreakpoint(
        columnCount[0],
        this.sectionedArtworksForAllBreakpoints(
          this.props.artworks,
          columnCount
{'fraction_non_alphanumeric': 0.10569105691056911, 'fraction_numerical': 0.005182926829268293, 'mean_word_length': 2.930111821086262, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 41, 'https://': 1, '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': '5096704', 'n_tokens_mistral': 2928, 'n_tokens_neox': 2869, 'n_words': 676}