<commit_before>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

import { DiscussionsContext } from 'beatmap-discussions/discussions-context';
import * as React from 'react';
import Editor from './editor';

interface Props {
  beatmaps: Beatmap[];
  beatmapset: Beatmapset;
  currentBeatmap: Beatmap;
  currentDiscussions: BeatmapDiscussion[];
  currentUser: User;
  pinned?: boolean;
  setPinned?: (sticky: boolean) => void;
  stickTo?: React.RefObject<HTMLDivElement>;
}

// TODO: move to globals.d.ts
interface StickyHeader {
  headerHeight: () => number;
}

declare global {
  interface Window {
    stickyHeader: StickyHeader;
  }
}

export default class NewReview extends React.Component<Props> {
  initialValue: string;
  placeholder: string = '[{"children": [{"text": "placeholder"}], "type": "paragraph"}]';

  constructor(props: Props) {
    super(props);

    const savedValue = localStorage.getItem(`newDiscussion-${this.props.beatmapset.id}`);
    this.initialValue = savedValue || this.placeholder;
    this.state = {
      cssTop: null,
    };
  }

  componentDidMount(): void {
    this.setTop();
    $(window).on('throttled-resize.new-review', this.setTop);
  }

  componentWillUnmount(): void {
    $(window).off('.new-review');
  }

  cssTop = (sticky: boolean) => {
    if (!sticky || !this.props.stickTo?.current) {
      return;
    }
<commit_msg>Fix state typing<commit_after>// Copyright (c) ppy Pty Ltd <<EMAIL>>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

import { DiscussionsContext } from 'beatmap-discussions/discussions-context';
import * as React from 'react';
import Editor from './editor';

interface Props {
  beatmaps: Beatmap[];
  beatmapset: Beatmapset;
  currentBeatmap: Beatmap;
  currentDiscussions: BeatmapDiscussion[];
  currentUser: User;
  pinned?: boolean;
  setPinned?: (sticky: boolean) => void;
  stickTo?: React.RefObject<HTMLDivElement>;
}

interface State {
  cssTop: string | number | undefined;
}

// TODO: move to globals.d.ts
interface StickyHeader {
  headerHeight: () => number;
}

declare global {
  interface Window {
    stickyHeader: StickyHeader;
  }
}

export default class NewReview extends React.Component<Props, State> {
  initialValue: string;
  placeholder: string = '[{"children": [{"text": "placeholder"}], "type": "paragraph"}]';

  constructor(props: Props) {
    super(props);

    const savedValue = localStorage.getItem(`newDiscussion-${this.props.beatmapset.id}`);
    this.initialValue = savedValue || this.placeholder;
    this.state = {
      cssTop: undefined,
    };
  }

  componentDidMount(): void {
    this.setTop();
    $(window).on('throttled-resize.new-review', this.setTop);
  }

  componentWillUnmount(): void {
    $(window).off('.new-review');
  }

  cssTop = (sticky: boolean) => {
    if (!sticky || !this.props.stickTo?.current) {
      return;
    }

{'fraction_non_alphanumeric': 0.14182771044873896, 'fraction_numerical': 0.0013101867016049786, 'mean_word_length': 3.9820554649265905, 'pattern_counts': {'":': 6, '<': 11, '<?xml version=': 0, '>': 17, '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': '2556551', 'n_tokens_mistral': 971, 'n_tokens_neox': 954, 'n_words': 243}