您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

UploadImageButton.tsx 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import React, { useCallback, useRef } from 'react';
  2. import { WithTranslation } from 'react-i18next';
  3. import { makeStyles } from 'tss-react/mui';
  4. import { v4 as uuidv4 } from 'uuid';
  5. import { translate } from '../../base/i18n/functions';
  6. import Icon from '../../base/icons/components/Icon';
  7. import { IconPlus } from '../../base/icons/svg';
  8. import { withPixelLineHeight } from '../../base/styles/functions.web';
  9. import { type Image, VIRTUAL_BACKGROUND_TYPE } from '../constants';
  10. import { resizeImage } from '../functions';
  11. import logger from '../logger';
  12. interface IProps extends WithTranslation {
  13. /**
  14. * Callback used to set the 'loading' state of the parent component.
  15. */
  16. setLoading: Function;
  17. /**
  18. * Callback used to set the options.
  19. */
  20. setOptions: Function;
  21. /**
  22. * Callback used to set the storedImages array.
  23. */
  24. setStoredImages: Function;
  25. /**
  26. * If a label should be displayed alongside the button.
  27. */
  28. showLabel: boolean;
  29. /**
  30. * A list of images locally stored.
  31. */
  32. storedImages: Array<Image>;
  33. }
  34. const useStyles = makeStyles()(theme => {
  35. return {
  36. label: {
  37. ...withPixelLineHeight(theme.typography.bodyShortBold),
  38. color: theme.palette.link01,
  39. marginBottom: theme.spacing(3),
  40. cursor: 'pointer',
  41. display: 'flex',
  42. alignItems: 'center'
  43. },
  44. addBackground: {
  45. marginRight: theme.spacing(3),
  46. '& svg': {
  47. fill: `${theme.palette.link01} !important`
  48. }
  49. },
  50. input: {
  51. display: 'none'
  52. }
  53. };
  54. });
  55. /**
  56. * Component used to upload an image.
  57. *
  58. * @param {Object} Props - The props of the component.
  59. * @returns {React$Node}
  60. */
  61. function UploadImageButton({
  62. setLoading,
  63. setOptions,
  64. setStoredImages,
  65. showLabel,
  66. storedImages,
  67. t
  68. }: IProps) {
  69. const { classes } = useStyles();
  70. const uploadImageButton = useRef<HTMLInputElement>(null);
  71. const uploadImageKeyPress = useCallback(e => {
  72. if (uploadImageButton.current && (e.key === ' ' || e.key === 'Enter')) {
  73. e.preventDefault();
  74. uploadImageButton.current.click();
  75. }
  76. }, [ uploadImageButton.current ]);
  77. const uploadImage = useCallback(async e => {
  78. const reader = new FileReader();
  79. const imageFile = e.target.files;
  80. reader.readAsDataURL(imageFile[0]);
  81. reader.onload = async () => {
  82. const url = await resizeImage(reader.result);
  83. const uuId = uuidv4();
  84. setStoredImages([
  85. ...storedImages,
  86. {
  87. id: uuId,
  88. src: url
  89. }
  90. ]);
  91. setOptions({
  92. backgroundType: VIRTUAL_BACKGROUND_TYPE.IMAGE,
  93. enabled: true,
  94. url,
  95. selectedThumbnail: uuId
  96. });
  97. };
  98. logger.info('New virtual background image uploaded!');
  99. reader.onerror = () => {
  100. setLoading(false);
  101. logger.error('Failed to upload virtual image!');
  102. };
  103. }, [ storedImages ]);
  104. return (
  105. <>
  106. {showLabel && <label
  107. className = { classes.label }
  108. htmlFor = 'file-upload'
  109. onKeyPress = { uploadImageKeyPress }
  110. tabIndex = { 0 } >
  111. <Icon
  112. className = { classes.addBackground }
  113. size = { 24 }
  114. src = { IconPlus } />
  115. {t('virtualBackground.addBackground')}
  116. </label>}
  117. <input
  118. accept = 'image/*'
  119. className = { classes.input }
  120. id = 'file-upload'
  121. onChange = { uploadImage }
  122. ref = { uploadImageButton }
  123. type = 'file' />
  124. </>
  125. );
  126. }
  127. export default translate(UploadImageButton);