You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

UploadImageButton.js 3.8KB

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