<commit_before>// @flow
import * as ICONS from 'constants/icons';
import React, { useEffect, useState } from 'react';
import CreditAmount from 'component/common/credit-amount';
import Button from 'component/button';
import { Form, FormField } from 'component/common/form';
import Card from 'component/common/card';
import I18nMessage from 'component/i18nMessage';

type Props = {
  balance: number,
  totalBalance: number,
  claimsBalance: number,
  supportsBalance: number,
  tipsBalance: number,
  claim: any,
  metaData: any,
  handleClose: () => void,
  abandonSupportForClaim: (string, string, boolean | string, boolean) => any,
  abandonClaimError: ?string,
};

const SupportsLiquidate = (props: Props) => {
  const { claim, abandonSupportForClaim, handleClose, abandonClaimError } = props;
  const [previewBalance, setPreviewBalance] = useState(undefined);
  const [amount, setAmount] = useState(0);
  const [error, setError] = useState(false);
  const initialMessage = '';
  const [message, setMessage] = useState(initialMessage);
  const keep =
    previewBalance && amount && Number(amount) < previewBalance
      ? Number.parseFloat(String(previewBalance - Number(amount))).toFixed(8)
      : false;
  const claimId = claim && claim.claim_id;
  const type = claim.value_type;

  useEffect(() => {
    if (claimId && abandonSupportForClaim) {
      abandonSupportForClaim(claimId, type, false, true).then(r => {
        setPreviewBalance(r.total_input);
      });
    }
  }, [abandonSupportForClaim, claimId, type, setPreviewBalance]);

  function handleSubmit() {
    abandonSupportForClaim(claimId, type, keep, false).then(r => {
      if (r) {
        handleClose();
      }
    });
  }

  function handleChange(a) {
    if (a === undefined || isNaN(Number(a))) {
      setMessage(__('Amount must be a number'));
      setError(true);
      setAmount('');
    } else if (a === '') {
      setAmount('');
      setError(true);
      setMessage(__('Amount cannot be blank'));
    } else if (Number(a) > Number(previewBalance)) {
      setMessage(__('Amount cannot be more than available'));
      setError(false);
    } else if (Number(a) === Number(previewBalance)) {
      setMessage(__(`She's about to close up the library!`));
      setAmount(a);
      setError(false);
    } else if (Number(a) > Number(previewBalance) / 2) {
      setMessage(__('Your content will do better with more staked on it'));
      setAmount(a);
      setError(false);
    } else if (a === '0') {
      setMessage(__('Amount cannot be zero'));
      setAmount(a);
      setError(true);
    } else {
      setMessage(initialMessage);
      setAmount(a);
      setError(false);
    }
  }

  return (
    <Card
      icon={ICONS.UNLOCK}
      title={__('Unlock Tips')}
      subtitle={
        <>
          <p>
            {__('You can unlock all or some of this LBC at any time.')}{' '}
            {__('Keeping it locked improves the trust and discoverability of your content.')}
          </p>
          <p>
            <I18nMessage
              tokens={{
                learn_more: <Button button="link" label={__('Learn More')} href="https://lbry.com/faq/tipping" />,
              }}
            >
              It's usually only worth unlocking what you intend to use immediately. %learn_more%
            </I18nMessage>
          </p>
        </>
      }
      body={
        <>
          <div className="section">
            <I18nMessage
              tokens={{
                amount: (
                  <strong>
                    <CreditAmount badge={false} amount={Number(previewBalance)} precision={8} />
                  </strong>
                ),
              }}
            >
              %amount% available to unlock
            </I18nMessage>
          </div>
          <div className="section">
            {previewBalance === 0 && <p>{__('No unlockable tips available')}</p>}
            {previewBalance === undefined && <p>{__('Loading...')}</p>}
            {previewBalance && (
              <Form onSubmit={handleSubmit}>
                <label htmlFor="supports_liquidate_range">{__('Amount to unlock')}</label>
                <FormField
                  name="supports_liquidate_range"
                  type={'range'}
                  min={0}
                  step={0.01}
                  max={previewBalance} // times 100 to so we're more granular than whole numbers.
                  value={Number(amount) || previewBalance / 4} // by default, set it to 25% of available
                  onChange={e => handleChange(e.target.value)}
                />
                <label className="range__label">
                  <span>0</span>
                  <span>{previewBalance / 2}</span>
                  <span>{previewBalance}</span>
                </label>
                <FormField
                  type="text"
                  value={amount || (previewBalance && previewBalance / 4)}
                  helper={message}
                  onChange={e => handleChange(e.target.value)}
                />
              </Form>
            )}
          </div>
        </>
      }
      actions={
        <React.Fragment>
          {abandonClaimError ? (
            <>
              <div className="error-text">{__('%message%', { message: abandonClaimError })}</div>
              <Button disabled={error} button="primary" onClick={handleClose} label={__('Done')} />
            </>
          ) : (
            <Button disabled={error} button="primary" onClick={handleSubmit} label={__('Unlock')} />
          )}
        </React.Fragment>
      }
    />
  );
};

export default SupportsLiquidate;
<commit_msg>fix tip select slider messaging and behavior<commit_after>// @flow
import * as ICONS from 'constants/icons';
import React, { useEffect, useState } from 'react';
import CreditAmount from 'component/common/credit-amount';
import Button from 'component/button';
import { Form, FormField } from 'component/common/form';
import Card from 'component/common/card';
import I18nMessage from 'component/i18nMessage';

type Props = {
  balance: number,
  totalBalance: number,
  claimsBalance: number,
  supportsBalance: number,
  tipsBalance: number,
  claim: any,
  metaData: any,
  handleClose: () => void,
  abandonSupportForClaim: (string, string, boolean | string, boolean) => any,
  abandonClaimError: ?string,
};

const SupportsLiquidate = (props: Props) => {
  const { claim, abandonSupportForClaim, handleClose, abandonClaimError } = props;
  const [previewBalance, setPreviewBalance] = useState(undefined);
  const [amount, setAmount] = useState(-1);
  const [error, setError] = useState(false);
  const initialMessage = __('How much would you like to unlock?');
  const [message, setMessage] = useState(initialMessage);
  const keep =
    previewBalance && amount && Number(amount) < previewBalance
      ? Number.parseFloat(String(previewBalance - Number(amount))).toFixed(8)
      : false;
  const claimId = claim && claim.claim_id;
  const type = claim.value_type;

  useEffect(() => {
    if (claimId && abandonSupportForClaim) {
      abandonSupportForClaim(claimId, type, false, true).then(r => {
        setPreviewBalance(r.total_input);
      });
    }
  }, [abandonSupportForClaim, claimId, type, setPreviewBalance]);

  function handleSubmit() {
    abandonSupportForClaim(claimId, type, keep, false).then(r => {
      if (r) {
        handleClose();
      }
    });
  }

  function handleChange(a) {
    if (a === undefined || isNaN(Number(a))) {
      setMessage(__('Amount must be a number'));
      setError(true);
      setAmount(0);
    } else if (a === '') {
      setAmount(0);
      setError(true);
      setMessage(__('Amount cannot be blank'));
    } else if (Number(a) > Number(previewBalance)) {
      setMessage(__('Amount cannot be more than available'));
      setError(false);
    } else if (Number(a) === Number(previewBalance)) {
      setMessage(__(`She's about to close up the library!`));
      setAmount(a);
      setError(false);
    } else if (Number(a) > Number(previewBalance) / 2) {
      setMessage(__('Your content will do better with more staked on it'));
      setAmount(a);
      setError(false);
    } else if (Number(a) === 0) {
      setMessage(__('Amount cannot be zero'));
      setAmount(0);
      setError(true);
    } else if (Number(a) <= Number(previewBalance) / 2) {
      setMessage(__('A prudent choice'));
      setAmount(Number(a));
      setError(false);
    } else {
      setMessage(initialMessage);
      setAmount(a);
      setError(false);
    }
  }

  return (
    <Card
      icon={ICONS.UNLOCK}
      title={__('Unlock Tips')}
      subtitle={
        <>
          <p>
            {__('You can unlock all or some of this LBC at any time.')}{' '}
            {__('Keeping it locked improves the trust and discoverability of your content.')}
          </p>
          <p>
            <I18nMessage
              tokens={{
                learn_more: <Button button="link" label={__('Learn More')} href="https://lbry.com/faq/tipping" />,
              }}
            >
              It's usually only worth unlocking what you intend to use immediately. %learn_more%
            </I18nMessage>
          </p>
        </>
      }
      body={
        <>
          <div className="section">
            <I18nMessage
              tokens={{
                amount: (
                  <strong>
                    <CreditAmount badge={false} amount={Number(previewBalance)} precision={8} />
                  </strong>
                ),
              }}
            >
              %amount% available to unlock
            </I18nMessage>
          </div>
          <div className="section">
            {previewBalance === 0 && <p>{__('No unlockable tips available')}</p>}
            {previewBalance === undefined && <p>{__('Loading...')}</p>}
            {previewBalance && (
              <Form onSubmit={handleSubmit}>
                <label htmlFor="supports_liquidate_range">{__('Amount to unlock')}</label>
                <FormField
                  name="supports_liquidate_range"
                  type={'range'}
                  min={0}
                  step={0.01}
                  max={previewBalance}
                  value={Number(amount) >= 0 ? amount : previewBalance / 4} // by default, set it to 25% of available
                  onChange={e => handleChange(e.target.value)}
                />
                <label className="range__label">
                  <span>0</span>
                  <span>{previewBalance / 2}</span>
                  <span>{previewBalance}</span>
                </label>
                <FormField
                  type="text"
                  value={amount >= 0 ? amount || '' : previewBalance && previewBalance / 4}
                  helper={message}
                  onChange={e => handleChange(e.target.value)}
                />
              </Form>
            )}
          </div>
        </>
      }
      actions={
        <React.Fragment>
          {abandonClaimError ? (
            <>
              <div className="error-text">{__('%message%', { message: abandonClaimError })}</div>
              <Button disabled={error} button="primary" onClick={handleClose} label={__('Done')} />
            </>
          ) : (
            <Button disabled={error} button="primary" onClick={handleSubmit} label={__('Unlock')} />
          )}
        </React.Fragment>
      }
    />
  );
};

export default SupportsLiquidate;

{'fraction_non_alphanumeric': 0.13838120104438642, 'fraction_numerical': 0.005657093124456049, 'mean_word_length': 2.065084022405975, 'pattern_counts': {'":': 0, '<': 100, '<?xml version=': 0, '>': 119, 'https://': 2, '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': '4612800', 'n_tokens_mistral': 3260, 'n_tokens_neox': 3203, 'n_words': 749}