<commit_before>/**
 *    Copyright (c) ppy Pty Ltd <<EMAIL>>.
 *
 *    This file is part of osu!web. osu!web is distributed with the hope of
 *    attracting more community contributions to the core ecosystem of osu!.
 *
 *    osu!web is free software: you can redistribute it and/or modify
 *    it under the terms of the Affero GNU General Public License version 3
 *    as published by the Free Software Foundation.
 *
 *    osu!web is distributed WITHOUT ANY WARRANTY; without even the implied
 *    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *    See the GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with osu!web.  If not, see <http://www.gnu.org/licenses/>.
 */

import { route } from 'laroute';
import { debounce } from 'lodash';
import { action, computed, observable } from 'mobx';

interface SuggestionJSON {
  highlight: string;
  path: string;
  title: string;
}

export class WikiSearchController {
  @observable direction = 0;
  @observable query = '';
  @observable selectedIndex = -1;
  @observable shouldShowSuggestions = false;
  @observable suggestions: SuggestionJSON[] = [];

  private getSuggestionsDebounced = debounce(this.getSuggestions, 200);
  private saved = '';
  private xhr?: JQueryXHR;

  @computed get isSuggestionsVisible() {
    return this.shouldShowSuggestions && this.suggestions.length > 0;
  }

  @computed get selectedItem(): SuggestionJSON | undefined {
    return this.suggestions[this.selectedIndex];
  }

  @action
  cancel() {
    this.xhr?.abort();
    this.getSuggestionsDebounced.cancel();
  }

  @action
  getSuggestions() {
    this.xhr?.abort();
    this.xhr = $.getJSON(route('wiki-suggestions'), { query: this.query.trim() })
    .done(action((response) => {
      if (response != null) {
        this.suggestions = response as SuggestionJSON[];
        this.shouldShowSuggestions = true;
      }
    }));
  }

  @action
  search() {
    const query = this.query.trim();

    if (query === '') {
      return;
    }

    Turbolinks.visit(route('search', {
      mode: 'wiki_page',
      query,
    }));
  }

  @action
  selectIndex(index: number, direction: number) {
    if (index < -1 || index >= this.suggestions.length) return;

    this.selectedIndex = index;
    this.direction = direction;

    if (direction === 0) return;

    if (index < 0) {
      this.query = this.saved;
      this.shouldShowSuggestions = false;
    } else {
      this.query = this.suggestions[index].title;
      this.shouldShowSuggestions = true;
    }
  }

  @action
  shiftSelectedIndex(direction: number) {
    this.selectIndex(this.selectedIndex + direction, direction);
  }

  @action
  updateQuery(query: string) {
    this.saved = this.query = query;

    if (this.query.trim().length === 0) {
      this.suggestions = [];
    }

    if (this.query.trim().length > 1) {
      this.getSuggestionsDebounced();
    }
  }
}<commit_msg>abort in wrong place<commit_after>/**
 *    Copyright (c) ppy Pty Ltd <<EMAIL>>.
 *
 *    This file is part of osu!web. osu!web is distributed with the hope of
 *    attracting more community contributions to the core ecosystem of osu!.
 *
 *    osu!web is free software: you can redistribute it and/or modify
 *    it under the terms of the Affero GNU General Public License version 3
 *    as published by the Free Software Foundation.
 *
 *    osu!web is distributed WITHOUT ANY WARRANTY; without even the implied
 *    warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *    See the GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with osu!web.  If not, see <http://www.gnu.org/licenses/>.
 */

import { route } from 'laroute';
import { debounce } from 'lodash';
import { action, computed, observable } from 'mobx';

interface SuggestionJSON {
  highlight: string;
  path: string;
  title: string;
}

export class WikiSearchController {
  @observable direction = 0;
  @observable query = '';
  @observable selectedIndex = -1;
  @observable shouldShowSuggestions = false;
  @observable suggestions: SuggestionJSON[] = [];

  private getSuggestionsDebounced = debounce(this.getSuggestions, 200);
  private saved = '';
  private xhr?: JQueryXHR;

  @computed get isSuggestionsVisible() {
    return this.shouldShowSuggestions && this.suggestions.length > 0;
  }

  @computed get selectedItem(): SuggestionJSON | undefined {
    return this.suggestions[this.selectedIndex];
  }

  @action
  cancel() {
    this.xhr?.abort();
    this.getSuggestionsDebounced.cancel();
  }

  @action
  search() {
    const query = this.query.trim();

    if (query === '') {
      return;
    }

    Turbolinks.visit(route('search', {
      mode: 'wiki_page',
      query,
    }));
  }

  @action
  selectIndex(index: number, direction: number) {
    if (index < -1 || index >= this.suggestions.length) return;

    this.selectedIndex = index;
    this.direction = direction;

    if (direction === 0) return;

    if (index < 0) {
      this.query = this.saved;
      this.shouldShowSuggestions = false;
    } else {
      this.query = this.suggestions[index].title;
      this.shouldShowSuggestions = true;
    }
  }

  @action
  shiftSelectedIndex(direction: number) {
    this.selectIndex(this.selectedIndex + direction, direction);
  }

  @action
  updateQuery(query: string) {
    this.saved = this.query = query;

    if (this.query.trim().length === 0) {
      this.suggestions = [];
    }

    if (this.query.trim().length > 1) {
      this.xhr?.abort();
      this.getSuggestionsDebounced();
    }
  }

  @action
  private getSuggestions() {
    this.xhr = $.getJSON(route('wiki-suggestions'), { query: this.query.trim() })
    .done(action((response) => {
      if (response != null) {
        this.suggestions = response as SuggestionJSON[];
        this.shouldShowSuggestions = true;
      }
    }));
  }
}
{'fraction_non_alphanumeric': 0.12040578746050225, 'fraction_numerical': 0.0039913520705138865, 'mean_word_length': 3.04983164983165, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '5387382', 'n_tokens_mistral': 1893, 'n_tokens_neox': 1804, 'n_words': 514}