<commit_before>/* eslint-disable react/forbid-prop-types */
import React from 'react';
import PropTypes from 'prop-types';
import { TextInput, View, StyleSheet } from 'react-native';

import { parsePositiveInteger } from '../utilities';

import { CircleButton } from './CircleButton';
import { AddIcon, MinusIcon } from './icons';

import { APP_FONT_FAMILY } from '../globalStyles';

/**
 * Input component which will update a numerical value. The `value` passed will be
 * cast, so should return a valid number when cast to `Number`.
 *
 * Has increment and decrement buttons which increase the passed value by one.
 * The buttons can also be held, increase by one every 50ms. The increment amount
 * then grows exponentially every 500ms, reseting to one after releasing.
 *
 * Component uses state to update itself, and a ref for storing the current value as
 * this is far more responsive than updating the redux store and re-rendering every 50ms.
 *
 * @prop {String|Number} value          The current numerical value.
 * @prop {Func}          onChangeText   Callback for updating the value.
 * @prop {Number}        lowerLimit     The lower limit of the numerical range.
 * @prop {Number}        upperLimit     The upper limit of the numerical range.
 * @prop {Object}        textInputStyle Style object for the underlying TextInput.
 * @prop {Bool}          isDisabled     Indicator if this component should be editable.
 *
 */
export const StepperInput = React.memo(
  ({ value, onChangeText, lowerLimit, upperLimit, textInputStyle, isDisabled }) => {
    const [, setCurrentValueState] = React.useState(Number(value));
    const currentValue = React.useRef(Number(value));
    const currentAdjustmentAmount = React.useRef(1);
    const valueAdjustmentInterval = React.useRef();
    const adjustmentIncreaseInterval = React.useRef();

    const parseNumber = number =>
      Math.max(Math.min(parsePositiveInteger(number), upperLimit), lowerLimit);

    const onUpdate = newValue => {
      const updateValue = parseNumber(newValue);
      currentValue.current = updateValue;
      setCurrentValueState(updateValue);
    };

    const decrementValue = () => onUpdate(currentValue.current - currentAdjustmentAmount.current);
    const incrementValue = () => onUpdate(currentValue.current + currentAdjustmentAmount.current);

    const inreaseIncrement = () => {
      currentAdjustmentAmount.current *= 2;
    };

    const onStartingLongPress = isIncrement => {
      if (isIncrement) incrementValue();
      else decrementValue();

      if (!valueAdjustmentInterval.current) {
        valueAdjustmentInterval.current = setInterval(
          isIncrement ? incrementValue : decrementValue,
          50
        );
      }

      if (!adjustmentIncreaseInterval.current) {
        adjustmentIncreaseInterval.current = setInterval(inreaseIncrement, 500);
      }
    };

    const onEndLongPress = () => {
      clearInterval(valueAdjustmentInterval.current);
      clearInterval(adjustmentIncreaseInterval.current);

      valueAdjustmentInterval.current = null;
      adjustmentIncreaseInterval.current = null;
      currentAdjustmentAmount.current = 1;<commit_msg>Add adjustment to interval timer<commit_after>/* eslint-disable react/forbid-prop-types */
import React from 'react';
import PropTypes from 'prop-types';
import { TextInput, View, StyleSheet } from 'react-native';

import { parsePositiveInteger } from '../utilities';

import { CircleButton } from './CircleButton';
import { AddIcon, MinusIcon } from './icons';

import { APP_FONT_FAMILY } from '../globalStyles';

/**
 * Input component which will update a numerical value. The `value` passed will be
 * cast, so should return a valid number when cast to `Number`.
 *
 * Has increment and decrement buttons which increase the passed value by one.
 * The buttons can also be held, increase by one every 50ms. The increment amount
 * then grows exponentially every 500ms, reseting to one after releasing.
 *
 * Component uses state to update itself, and a ref for storing the current value as
 * this is far more responsive than updating the redux store and re-rendering every 50ms.
 *
 * @prop {String|Number} value          The current numerical value.
 * @prop {Func}          onChangeText   Callback for updating the value.
 * @prop {Number}        lowerLimit     The lower limit of the numerical range.
 * @prop {Number}        upperLimit     The upper limit of the numerical range.
 * @prop {Object}        textInputStyle Style object for the underlying TextInput.
 * @prop {Bool}          isDisabled     Indicator if this component should be editable.
 *
 */
export const StepperInput = React.memo(
  ({ value, onChangeText, lowerLimit, upperLimit, textInputStyle, isDisabled }) => {
    const [, setCurrentValueState] = React.useState(Number(value));
    const currentValue = React.useRef(Number(value));
    const currentAdjustmentAmount = React.useRef(1);
    const valueAdjustmentInterval = React.useRef();
    const adjustmentIncreaseInterval = React.useRef();

    const parseNumber = number =>
      Math.max(Math.min(parsePositiveInteger(number), upperLimit), lowerLimit);

    const onUpdate = newValue => {
      const updateValue = parseNumber(newValue);
      currentValue.current = updateValue;
      setCurrentValueState(updateValue);
    };

    const decrementValue = () => onUpdate(currentValue.current - currentAdjustmentAmount.current);
    const incrementValue = () => onUpdate(currentValue.current + currentAdjustmentAmount.current);

    const inreaseIncrement = () => {
      currentAdjustmentAmount.current *= 2;
    };

    const onStartingLongPress = isIncrement => {
      if (isIncrement) incrementValue();
      else decrementValue();

      if (!valueAdjustmentInterval.current) {
        valueAdjustmentInterval.current = setInterval(
          isIncrement ? incrementValue : decrementValue,
          150
        );
      }

      if (!adjustmentIncreaseInterval.current) {
        adjustmentIncreaseInterval.current = setInterval(inreaseIncrement, 500);
      }
    };

    const onEndLongPress = () => {
      clearInterval(valueAdjustmentInterval.current);
      clearInterval(adjustmentIncreaseInterval.current);

      valueAdjustmentInterval.current = null;
      adjustmentIncreaseInterval.current = null;
      currentAdjustmentAmount.current = 1;
{'fraction_non_alphanumeric': 0.09205152371976123, 'fraction_numerical': 0.00486961985548225, 'mean_word_length': 3.570710696338837, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, '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': '3367872', 'n_tokens_mistral': 1697, 'n_tokens_neox': 1625, 'n_words': 523}