Rewrite <ShortNumber /> as FC and TS (#25492)
		
	This commit is contained in:
		
					parent
					
						
							
								e0d230fb37
							
						
					
				
			
			
				commit
				
					
						20e85c0e83
					
				
			
		
					 10 changed files with 98 additions and 123 deletions
				
			
		|  | @ -9,7 +9,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; | |||
| import ImmutablePureComponent from 'react-immutable-pure-component'; | ||||
| 
 | ||||
| import { EmptyAccount } from 'mastodon/components/empty_account'; | ||||
| import ShortNumber from 'mastodon/components/short_number'; | ||||
| import { ShortNumber } from 'mastodon/components/short_number'; | ||||
| import { VerifiedBadge } from 'mastodon/components/verified_badge'; | ||||
| 
 | ||||
| import { me } from '../initial_state'; | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import { TransitionMotion, spring } from 'react-motion'; | |||
| 
 | ||||
| import { reduceMotion } from '../initial_state'; | ||||
| 
 | ||||
| import ShortNumber from './short_number'; | ||||
| import { ShortNumber } from './short_number'; | ||||
| 
 | ||||
| const obfuscatedCount = (count: number) => { | ||||
|   if (count < 0) { | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| import { FormattedMessage } from 'react-intl'; | ||||
| 
 | ||||
| import ShortNumber from 'mastodon/components/short_number'; | ||||
| import { ShortNumber } from 'mastodon/components/short_number'; | ||||
| 
 | ||||
| interface Props { | ||||
|   tag: { | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; | |||
| 
 | ||||
| import { Sparklines, SparklinesCurve } from 'react-sparklines'; | ||||
| 
 | ||||
| import ShortNumber from 'mastodon/components/short_number'; | ||||
| import { ShortNumber } from 'mastodon/components/short_number'; | ||||
| import { Skeleton } from 'mastodon/components/skeleton'; | ||||
| 
 | ||||
| class SilentErrorBoundary extends Component { | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ import { connect } from 'react-redux'; | |||
| 
 | ||||
| import { fetchServer } from 'mastodon/actions/server'; | ||||
| import { ServerHeroImage } from 'mastodon/components/server_hero_image'; | ||||
| import ShortNumber from 'mastodon/components/short_number'; | ||||
| import { ShortNumber } from 'mastodon/components/short_number'; | ||||
| import { Skeleton } from 'mastodon/components/skeleton'; | ||||
| import Account from 'mastodon/containers/account_container'; | ||||
| import { domain } from 'mastodon/initial_state'; | ||||
|  |  | |||
|  | @ -1,115 +0,0 @@ | |||
| import PropTypes from 'prop-types'; | ||||
| import { memo } from 'react'; | ||||
| 
 | ||||
| import { FormattedMessage, FormattedNumber } from 'react-intl'; | ||||
| 
 | ||||
| import { toShortNumber, pluralReady, DECIMAL_UNITS } from '../utils/numbers'; | ||||
| 
 | ||||
| // @ts-check | ||||
| 
 | ||||
| /** | ||||
|  * @callback ShortNumberRenderer | ||||
|  * @param {JSX.Element} displayNumber Number to display | ||||
|  * @param {number} pluralReady Number used for pluralization | ||||
|  * @returns {JSX.Element} Final render of number | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * @typedef {object} ShortNumberProps | ||||
|  * @property {number} value Number to display in short variant | ||||
|  * @property {ShortNumberRenderer} [renderer] | ||||
|  * Custom renderer for numbers, provided as a prop. If another renderer | ||||
|  * passed as a child of this component, this prop won't be used. | ||||
|  * @property {ShortNumberRenderer} [children] | ||||
|  * Custom renderer for numbers, provided as a child. If another renderer | ||||
|  * passed as a prop of this component, this one will be used instead. | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * Component that renders short big number to a shorter version | ||||
|  * @param {ShortNumberProps} param0 Props for the component | ||||
|  * @returns {JSX.Element} Rendered number | ||||
|  */ | ||||
| function ShortNumber({ value, renderer, children }) { | ||||
|   const shortNumber = toShortNumber(value); | ||||
|   const [, division] = shortNumber; | ||||
| 
 | ||||
|   if (children != null && renderer != null) { | ||||
|     console.warn('Both renderer prop and renderer as a child provided. This is a mistake and you really should fix that. Only renderer passed as a child will be used.'); | ||||
|   } | ||||
| 
 | ||||
|   const customRenderer = children != null ? children : renderer; | ||||
| 
 | ||||
|   const displayNumber = <ShortNumberCounter value={shortNumber} />; | ||||
| 
 | ||||
|   return customRenderer != null | ||||
|     ? customRenderer(displayNumber, pluralReady(value, division)) | ||||
|     : displayNumber; | ||||
| } | ||||
| 
 | ||||
| ShortNumber.propTypes = { | ||||
|   value: PropTypes.number.isRequired, | ||||
|   renderer: PropTypes.func, | ||||
|   children: PropTypes.func, | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * @typedef {object} ShortNumberCounterProps | ||||
|  * @property {import('../utils/number').ShortNumber} value Short number | ||||
|  */ | ||||
| 
 | ||||
| /** | ||||
|  * Renders short number into corresponding localizable react fragment | ||||
|  * @param {ShortNumberCounterProps} param0 Props for the component | ||||
|  * @returns {JSX.Element} FormattedMessage ready to be embedded in code | ||||
|  */ | ||||
| function ShortNumberCounter({ value }) { | ||||
|   const [rawNumber, unit, maxFractionDigits = 0] = value; | ||||
| 
 | ||||
|   const count = ( | ||||
|     <FormattedNumber | ||||
|       value={rawNumber} | ||||
|       maximumFractionDigits={maxFractionDigits} | ||||
|     /> | ||||
|   ); | ||||
| 
 | ||||
|   let values = { count, rawNumber }; | ||||
| 
 | ||||
|   switch (unit) { | ||||
|   case DECIMAL_UNITS.THOUSAND: { | ||||
|     return ( | ||||
|       <FormattedMessage | ||||
|         id='units.short.thousand' | ||||
|         defaultMessage='{count}K' | ||||
|         values={values} | ||||
|       /> | ||||
|     ); | ||||
|   } | ||||
|   case DECIMAL_UNITS.MILLION: { | ||||
|     return ( | ||||
|       <FormattedMessage | ||||
|         id='units.short.million' | ||||
|         defaultMessage='{count}M' | ||||
|         values={values} | ||||
|       /> | ||||
|     ); | ||||
|   } | ||||
|   case DECIMAL_UNITS.BILLION: { | ||||
|     return ( | ||||
|       <FormattedMessage | ||||
|         id='units.short.billion' | ||||
|         defaultMessage='{count}B' | ||||
|         values={values} | ||||
|       /> | ||||
|     ); | ||||
|   } | ||||
|   // Not sure if we should go farther - @Sasha-Sorokin | ||||
|   default: return count; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| ShortNumberCounter.propTypes = { | ||||
|   value: PropTypes.arrayOf(PropTypes.number), | ||||
| }; | ||||
| 
 | ||||
| export default memo(ShortNumber); | ||||
							
								
								
									
										90
									
								
								app/javascript/mastodon/components/short_number.tsx
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								app/javascript/mastodon/components/short_number.tsx
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,90 @@ | |||
| import { memo } from 'react'; | ||||
| 
 | ||||
| import { FormattedMessage, FormattedNumber } from 'react-intl'; | ||||
| 
 | ||||
| import { toShortNumber, pluralReady, DECIMAL_UNITS } from '../utils/numbers'; | ||||
| 
 | ||||
| type ShortNumberRenderer = ( | ||||
|   displayNumber: JSX.Element, | ||||
|   pluralReady: number | ||||
| ) => JSX.Element; | ||||
| 
 | ||||
| interface ShortNumberProps { | ||||
|   value: number; | ||||
|   renderer?: ShortNumberRenderer; | ||||
|   children?: ShortNumberRenderer; | ||||
| } | ||||
| 
 | ||||
| export const ShortNumberRenderer: React.FC<ShortNumberProps> = ({ | ||||
|   value, | ||||
|   renderer, | ||||
|   children, | ||||
| }) => { | ||||
|   const shortNumber = toShortNumber(value); | ||||
|   const [, division] = shortNumber; | ||||
| 
 | ||||
|   if (children && renderer) { | ||||
|     console.warn( | ||||
|       'Both renderer prop and renderer as a child provided. This is a mistake and you really should fix that. Only renderer passed as a child will be used.' | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   const customRenderer = children || renderer || null; | ||||
| 
 | ||||
|   const displayNumber = <ShortNumberCounter value={shortNumber} />; | ||||
| 
 | ||||
|   return ( | ||||
|     customRenderer?.(displayNumber, pluralReady(value, division)) || | ||||
|     displayNumber | ||||
|   ); | ||||
| }; | ||||
| export const ShortNumber = memo(ShortNumberRenderer); | ||||
| 
 | ||||
| interface ShortNumberCounterProps { | ||||
|   value: number[]; | ||||
| } | ||||
| const ShortNumberCounter: React.FC<ShortNumberCounterProps> = ({ value }) => { | ||||
|   const [rawNumber, unit, maxFractionDigits = 0] = value; | ||||
| 
 | ||||
|   const count = ( | ||||
|     <FormattedNumber | ||||
|       value={rawNumber} | ||||
|       maximumFractionDigits={maxFractionDigits} | ||||
|     /> | ||||
|   ); | ||||
| 
 | ||||
|   const values = { count, rawNumber }; | ||||
| 
 | ||||
|   switch (unit) { | ||||
|     case DECIMAL_UNITS.THOUSAND: { | ||||
|       return ( | ||||
|         <FormattedMessage | ||||
|           id='units.short.thousand' | ||||
|           defaultMessage='{count}K' | ||||
|           values={values} | ||||
|         /> | ||||
|       ); | ||||
|     } | ||||
|     case DECIMAL_UNITS.MILLION: { | ||||
|       return ( | ||||
|         <FormattedMessage | ||||
|           id='units.short.million' | ||||
|           defaultMessage='{count}M' | ||||
|           values={values} | ||||
|         /> | ||||
|       ); | ||||
|     } | ||||
|     case DECIMAL_UNITS.BILLION: { | ||||
|       return ( | ||||
|         <FormattedMessage | ||||
|           id='units.short.billion' | ||||
|           defaultMessage='{count}B' | ||||
|           values={values} | ||||
|         /> | ||||
|       ); | ||||
|     } | ||||
|     // Not sure if we should go farther - @Sasha-Sorokin
 | ||||
|     default: | ||||
|       return count; | ||||
|   } | ||||
| }; | ||||
|  | @ -14,7 +14,7 @@ import Button from 'mastodon/components/button'; | |||
| import { FollowersCounter, FollowingCounter, StatusesCounter } from 'mastodon/components/counters'; | ||||
| import { Icon }  from 'mastodon/components/icon'; | ||||
| import { IconButton } from 'mastodon/components/icon_button'; | ||||
| import ShortNumber from 'mastodon/components/short_number'; | ||||
| import { ShortNumber } from 'mastodon/components/short_number'; | ||||
| import DropdownMenuContainer from 'mastodon/containers/dropdown_menu_container'; | ||||
| import { autoPlayGif, me, domain } from 'mastodon/initial_state'; | ||||
| import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions'; | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ import { openModal } from 'mastodon/actions/modal'; | |||
| import { Avatar } from 'mastodon/components/avatar'; | ||||
| import Button from 'mastodon/components/button'; | ||||
| import { DisplayName } from 'mastodon/components/display_name'; | ||||
| import ShortNumber from 'mastodon/components/short_number'; | ||||
| import { ShortNumber } from 'mastodon/components/short_number'; | ||||
| import { autoPlayGif, me, unfollowModal } from 'mastodon/initial_state'; | ||||
| import { makeGetAccount } from 'mastodon/selectors'; | ||||
| 
 | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import classNames from 'classnames'; | |||
| 
 | ||||
| import { Blurhash } from 'mastodon/components/blurhash'; | ||||
| import { accountsCountRenderer } from 'mastodon/components/hashtag'; | ||||
| import ShortNumber from 'mastodon/components/short_number'; | ||||
| import { ShortNumber } from 'mastodon/components/short_number'; | ||||
| import { Skeleton } from 'mastodon/components/skeleton'; | ||||
| 
 | ||||
| export default class Story extends PureComponent { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue