<commit_before>import { h, Component } from "preact";

import Masonry from "masonry-layout";

import Post from "components/post";

export default class Home extends Component {
  constructor(props) {
    super();
    this.state = {
      loaded: 0,
      initialLoaded: false,
      Pagination: props.Pagination,
      fetching: false
    };
    this.initialPosts = props.Posts.length;
    this.Masonry = false;

    // Wait this long for idle callbacks
    this.maxNotIdle = 750;

    // Less aggressive infinite scroll if the user has "Data Saver" turned on
    this.triggerDistance =
      "connection" in navigator && navigator.connection.saveData
        ? "0px"
        : "500px";
  }

  componentWillMount() {
    this.props.setPageType("index");
  }

  componentDidMount() {
    if (this.props.Posts.length > 0) {
      this.setupGrid();
    }

    // If the images are already cached / first page contains no "loadable" components they can be loaded before this component mounts
    if (this.props.Posts.length > 0 && this.state.loaded >= this.initialPosts) {
      requestAnimationFrame(() => {
        this.Masonry.layout();
        this.Masonry.once("layoutComplete", () => {
          this.setState({
            initialLoaded: true
          });
        });
      });
    }
  }

  componentWillUnmount() {
    this.cleanupGrid();
  }

  componentDidUpdate(prevProps) {
    // If you load up from a permalink and then go back to the homepage, this will trigger the infinite scroll "prefill"
    if (
      prevProps.Posts.length <= 0 &&
      this.props.Posts.length > 0 &&
      this.paginationTriggerInRange &&
      !this.state.fetching
    ) {
      this.runLoadNext();
    }
    if (this.props.Posts.length > 0 && prevProps.Posts.length <= 0) {
      this.setupGrid();
    }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.Posts.length > 0 && nextProps.Posts.length <= 0) {
      this.cleanupGrid();
    }
    if (this.props.Posts.length <= 0 && nextProps.Posts.length > 0) {
      this.initialPosts = nextProps.Posts.length;
      this.setupGrid();
    }
  }

  setupGrid() {
    if (!this.Masonry && this.props.Posts && this.props.Posts.length > 0) {
      // Masonry kinda freaks out if you try and set it up with no elements to layout, so I let the first page of elements
      this.Masonry = new Masonry(this.grid, {
        columnWidth: "article.sizer",
        itemSelector: "article:not(.sizer)",
        stamp: ".tag-header",
        percentPosition: true,
        initLayout: false,
        transitionDuration: 0
      });
      this.Masonry.once("layoutComplete", () => {
        // Trigger a re-render once Masonry is setup
        this.setState({});
      });
      this.setupInfiniteScroll();
    }
  }

  cleanupGrid() {
    this.setState({
      loaded: 0,
      initialLoaded: false,
      Pagination: this.props.Pagination,
      fetching: false
    });

    if (this.observer) {
      this.observer.disconnect();
      this.observer = null;
    }
    if (this.Masonry) {
      this.Masonry.destroy();
      this.Masonry = null;
    }
  }

  setupInfiniteScroll() {
    // Super simple hand-rolled infinite scroll using IntersectionObserver
    this.observer = new IntersectionObserver(
      entries => this.infiniteScrollCallback(entries),
      {
        rootMargin: this.triggerDistance
      }
    );
    this.observer.observe(this.trigger);
  }

  infiniteScrollCallback(entries = null) {
    // Keep track of the ratio as this callback only triggers when the element enters or leaves the screen
    this.paginationTriggerInRange = entries
      ? entries[0].intersectionRatio > 0
      : this.paginationTriggerInRange;
    console.log(this.paginationTriggerInRange);

    if (
      this.paginationTriggerInRange &&
      !this.state.fetching &&
      (this.props.Pagination() && this.props.Pagination().NextPage) &&
      this.state.initialLoaded
    ) {
      if (!!window.requestIdleCallback) {
        requestIdleCallback(
          () => {
            this.runLoadNext();
          },
          { timeout: this.maxNotIdle }
        );<commit_msg>removed console<commit_after>import { h, Component } from "preact";

import Masonry from "masonry-layout";

import Post from "components/post";

export default class Home extends Component {
  constructor(props) {
    super();
    this.state = {
      loaded: 0,
      initialLoaded: false,
      Pagination: props.Pagination,
      fetching: false
    };
    this.initialPosts = props.Posts.length;
    this.Masonry = false;

    // Wait this long for idle callbacks
    this.maxNotIdle = 750;

    // Less aggressive infinite scroll if the user has "Data Saver" turned on
    this.triggerDistance =
      "connection" in navigator && navigator.connection.saveData
        ? "0px"
        : "500px";
  }

  componentWillMount() {
    this.props.setPageType("index");
  }

  componentDidMount() {
    if (this.props.Posts.length > 0) {
      this.setupGrid();
    }

    // If the images are already cached / first page contains no "loadable" components they can be loaded before this component mounts
    if (this.props.Posts.length > 0 && this.state.loaded >= this.initialPosts) {
      requestAnimationFrame(() => {
        this.Masonry.layout();
        this.Masonry.once("layoutComplete", () => {
          this.setState({
            initialLoaded: true
          });
        });
      });
    }
  }

  componentWillUnmount() {
    this.cleanupGrid();
  }

  componentDidUpdate(prevProps) {
    // If you load up from a permalink and then go back to the homepage, this will trigger the infinite scroll "prefill"
    if (
      prevProps.Posts.length <= 0 &&
      this.props.Posts.length > 0 &&
      this.paginationTriggerInRange &&
      !this.state.fetching
    ) {
      this.runLoadNext();
    }
    if (this.props.Posts.length > 0 && prevProps.Posts.length <= 0) {
      this.setupGrid();
    }
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.Posts.length > 0 && nextProps.Posts.length <= 0) {
      this.cleanupGrid();
    }
    if (this.props.Posts.length <= 0 && nextProps.Posts.length > 0) {
      this.initialPosts = nextProps.Posts.length;
      this.setupGrid();
    }
  }

  setupGrid() {
    if (!this.Masonry && this.props.Posts && this.props.Posts.length > 0) {
      // Masonry kinda freaks out if you try and set it up with no elements to layout, so I let the first page of elements
      this.Masonry = new Masonry(this.grid, {
        columnWidth: "article.sizer",
        itemSelector: "article:not(.sizer)",
        stamp: ".tag-header",
        percentPosition: true,
        initLayout: false,
        transitionDuration: 0
      });
      this.Masonry.once("layoutComplete", () => {
        // Trigger a re-render once Masonry is setup
        this.setState({});
      });
      this.setupInfiniteScroll();
    }
  }

  cleanupGrid() {
    this.setState({
      loaded: 0,
      initialLoaded: false,
      Pagination: this.props.Pagination,
      fetching: false
    });

    if (this.observer) {
      this.observer.disconnect();
      this.observer = null;
    }
    if (this.Masonry) {
      this.Masonry.destroy();
      this.Masonry = null;
    }
  }

  setupInfiniteScroll() {
    // Super simple hand-rolled infinite scroll using IntersectionObserver
    this.observer = new IntersectionObserver(
      entries => this.infiniteScrollCallback(entries),
      {
        rootMargin: this.triggerDistance
      }
    );
    this.observer.observe(this.trigger);
  }

  infiniteScrollCallback(entries = null) {
    // Keep track of the ratio as this callback only triggers when the element enters or leaves the screen
    this.paginationTriggerInRange = entries
      ? entries[0].intersectionRatio > 0
      : this.paginationTriggerInRange;

    if (
      this.paginationTriggerInRange &&
      !this.state.fetching &&
      (this.props.Pagination() && this.props.Pagination().NextPage) &&
      this.state.initialLoaded
    ) {
      if (!!window.requestIdleCallback) {
        requestIdleCallback(
          () => {
            this.runLoadNext();
          },
          { timeout: this.maxNotIdle }
        );
{'fraction_non_alphanumeric': 0.11851761252446184, 'fraction_numerical': 0.005626223091976516, 'mean_word_length': 2.383119569714522, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 31, 'https://': 0, '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': '6845214', 'n_tokens_mistral': 2504, 'n_tokens_neox': 2402, 'n_words': 562}