<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 BeatmapExtendedJson from 'interfaces/beatmap-extended-json';
import { round } from 'lodash';
import * as React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { getDiffColour, getDiffRating } from 'utils/beatmap-helper';
import { classWithModifiers, Modifiers } from 'utils/css';
import { nextVal } from 'utils/seq';

interface Props {
  beatmap: BeatmapExtendedJson;
  modifiers?: Modifiers;
  showConvertMode: boolean;
  showTitle: boolean;
}

export class BeatmapIcon extends React.Component<Props> {
  static readonly defaultProps = {
    showConvertMode: false,
    showTitle: true,
  };

  private tooltipId = `beatmap-icon-${nextVal()}`;

  render() {
    const mode = this.props.beatmap.convert && !this.props.showConvertMode ? 'osu' : this.props.beatmap.mode;

    const className = classWithModifiers('beatmap-icon', this.props.modifiers, {
      'with-hover': this.props.showTitle,
    });

    const style = {
      '--diff': getDiffColour(this.props.beatmap.difficulty_rating),
    } as React.CSSProperties;

    return (
      <div
        className={className}
        onMouseOver={this.handleMouseOver}
        onTouchStart={this.handleMouseOver}
        style={style}
      >
        <i className={`fal fa-extra-mode-${mode}`} />
      </div>
    );
  }

  private readonly handleMouseOver = (event: React.SyntheticEvent<HTMLElement>) => {
    if (!this.props.showTitle) return;

    event.persist();
    const el = event.currentTarget;

    if (el._tooltip === this.tooltipId) return;

    const diffRating = getDiffRating(this.props.beatmap.difficulty_rating);
    const $content = $(renderToStaticMarkup(
      <div
        className='tooltip-beatmap'
        style={{
          '--diff': `var(--diff-${diffRating})`,
        } as React.CSSProperties}
      >
        <div className='tooltip-beatmap__text tooltip-beatmap__text--title'>{this.props.beatmap.version}</div>
        <div className='tooltip-beatmap__text'>
          {round(this.props.beatmap.difficulty_rating, 2)} <i aria-hidden='true' className='fas fa-star' />
        </div>
      </div>,
    ));

    if (el._tooltip != null) {
      el._tooltip = this.tooltipId;
      $(el).qtip('set', { 'content.text': $content });
      return;
    }

    el._tooltip = this.tooltipId;

    const options = {
      content: $content,
      hide: event.type === 'touchstart' ? {
        event: 'unfocus',
        inactive: 3000,
      } : {
        event: 'click mouseleave',
      },
      overwrite: false,
      position: {
        at: 'top center',
        my: 'bottom center',
        viewport: $(window),
      },
      show: {
        event: event.type,
        ready: true,
      },
      style: {
        classes: 'qtip qtip--tooltip-beatmap',
        tip: {
          height: 9,
          width: 10,
        },
      },
    };
<commit_msg>make tooltip go away if tapping again<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 BeatmapExtendedJson from 'interfaces/beatmap-extended-json';
import { round } from 'lodash';
import * as React from 'react';
import { renderToStaticMarkup } from 'react-dom/server';
import { getDiffColour, getDiffRating } from 'utils/beatmap-helper';
import { classWithModifiers, Modifiers } from 'utils/css';
import { nextVal } from 'utils/seq';

interface Props {
  beatmap: BeatmapExtendedJson;
  modifiers?: Modifiers;
  showConvertMode: boolean;
  showTitle: boolean;
}

export class BeatmapIcon extends React.Component<Props> {
  static readonly defaultProps = {
    showConvertMode: false,
    showTitle: true,
  };

  private tooltipId = `beatmap-icon-${nextVal()}`;

  render() {
    const mode = this.props.beatmap.convert && !this.props.showConvertMode ? 'osu' : this.props.beatmap.mode;

    const className = classWithModifiers('beatmap-icon', this.props.modifiers, {
      'with-hover': this.props.showTitle,
    });

    const style = {
      '--diff': getDiffColour(this.props.beatmap.difficulty_rating),
    } as React.CSSProperties;

    return (
      <div
        className={className}
        onMouseOver={this.handleMouseOver}
        onTouchStart={this.handleMouseOver}
        style={style}
      >
        <i className={`fal fa-extra-mode-${mode}`} />
      </div>
    );
  }

  private readonly handleMouseOver = (event: React.SyntheticEvent<HTMLElement>) => {
    if (!this.props.showTitle) return;

    event.persist();
    const el = event.currentTarget;

    // on touch devices, touchstart and then mouseover will trigger.
    // the following mouseover should be ignored in that case.
    if (el._tooltip === this.tooltipId) return;

    const diffRating = getDiffRating(this.props.beatmap.difficulty_rating);
    const $content = $(renderToStaticMarkup(
      <div
        className='tooltip-beatmap'
        style={{
          '--diff': `var(--diff-${diffRating})`,
        } as React.CSSProperties}
      >
        <div className='tooltip-beatmap__text tooltip-beatmap__text--title'>{this.props.beatmap.version}</div>
        <div className='tooltip-beatmap__text'>
          {round(this.props.beatmap.difficulty_rating, 2)} <i aria-hidden='true' className='fas fa-star' />
        </div>
      </div>,
    ));

    if (el._tooltip != null) {
      el._tooltip = this.tooltipId;
      $(el).qtip('set', { 'content.text': $content });
      return;
    }

    el._tooltip = this.tooltipId;

    const options = {
      content: $content,
      hide: event.type === 'touchstart' ? {
        event: 'touchstart unfocus',
        inactive: 3000,
      } : {
        event: 'click mouseleave',
      },
      overwrite: false,
      position: {
        at: 'top center',
        my: 'bottom center',
        viewport: $(window),
      },
      show: {
        event: event.type,
        ready: true,
      },
      style: {
        classes: 'qtip qtip--tooltip-beatmap',
        tip: {
          height: 9,
          width: 10,
        },
      },
    };

{'fraction_non_alphanumeric': 0.13564467167279118, 'fraction_numerical': 0.003195398625978591, 'mean_word_length': 2.6522753792298714, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 33, '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': '5621663', 'n_tokens_mistral': 1963, 'n_tokens_neox': 1903, 'n_words': 435}