Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

UploadImageButton.tsx 4.0KB

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