diff --git a/package.json b/package.json index 0568658e9..863f046cb 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "@redux-beacon/logger": "^1.0.0", "@redux-beacon/offline-web": "^1.0.0", "axios": "^0.26.1", - "browser-image-resizer": "^1.2.0", + "browser-image-resizer": "^2.4.1", "dom-to-image": "^2.6.0", "dotenv": "^16.1.4", "echarts": "5.4.3", diff --git a/src/components/Board/TileEditor/TileEditor.component.js b/src/components/Board/TileEditor/TileEditor.component.js index 03bf5de47..1678af743 100644 --- a/src/components/Board/TileEditor/TileEditor.component.js +++ b/src/components/Board/TileEditor/TileEditor.component.js @@ -34,7 +34,11 @@ import EditIcon from '@material-ui/icons/Edit'; import ImageEditor from '../ImageEditor'; import API from '../../../api'; -import { isAndroid, writeCvaFile } from '../../../cordova-util'; +import { + isAndroid, + requestCvaPermissions, + writeCvaFile +} from '../../../cordova-util'; import { convertImageUrlToCatchable } from '../../../helpers'; import PremiumFeature from '../../PremiumFeature'; @@ -119,12 +123,9 @@ export class TileEditor extends Component { this.setState({ editingTiles: props.editingTiles }); } componentDidUpdate(prevProps) { - if ( - this.props.open !== prevProps.open && - this.props.open && - this.editingTile() - ) { - this.setLinkedBoard(); + if (this.props.open !== prevProps.open && this.props.open) { + if (this.editingTile()) this.setLinkedBoard(); + if (isAndroid()) requestCvaPermissions(); } } diff --git a/src/components/UI/InputImage/InputImage.component.js b/src/components/UI/InputImage/InputImage.component.js index 97d421216..ea8149cbc 100644 --- a/src/components/UI/InputImage/InputImage.component.js +++ b/src/components/UI/InputImage/InputImage.component.js @@ -1,12 +1,29 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { injectIntl, intlShape } from 'react-intl'; -import { requestCvaPermissions, isCordova } from '../../../cordova-util'; +import { isAndroid } from '../../../cordova-util'; import PhotoCameraIcon from '@material-ui/icons/PhotoCamera'; -import readAndCompressImage from 'browser-image-resizer'; +import { readAndCompressImage } from 'browser-image-resizer'; import messages from './InputImage.messages'; import './InputImage.css'; +import Button from '@material-ui/core/Button'; +const configLQ = { + quality: 7, + maxWidth: 200, + maxHeight: 200, + autoRotate: true, + debug: false, + mimeType: 'image/png' +}; +const configHQ = { + quality: 1, + maxWidth: 800, + maxHeight: 800, + autoRotate: true, + debug: false, + mimeType: 'image/png' +}; class InputImage extends Component { static propTypes = { /** @@ -19,54 +36,90 @@ class InputImage extends Component { onChange: PropTypes.func.isRequired }; - async resizeImage(file, config) { - const resizedBlob = await readAndCompressImage(file, config); - return resizedBlob; + async resizeImage(file, imageName = null) { + //if you cancel the image uploaded, the event is dispached and the file is null + try { + const { onChange } = this.props; + const resizedBlob = await readAndCompressImage(file, configLQ); + const blobHQ = await readAndCompressImage(file, configHQ); + const fileName = imageName || file.name; + onChange(resizedBlob, fileName, blobHQ); + } catch (err) { + console.error(err); + } } + onClick = async () => { + try { + const imageURL = await window.cordova.plugins.safMediastore.selectFile(); + const imageName = await window.cordova.plugins.safMediastore.getFileName( + imageURL + ); + const file = await new Promise((resolve, reject) => { + window.resolveLocalFileSystemURL( + imageURL, + fileEntry => { + fileEntry.file( + file => { + resolve(file); + }, + err => { + console.error(err); + resolve(null); + } + ); + }, + err => { + console.error(err); + resolve(null); + } + ); + }); + + if (file) { + await this.resizeImage(file, imageName); + } + } catch (err) { + console.error(err); + } + }; + handleChange = async event => { const file = event.target.files[0]; - const configLQ = { - quality: 7, - maxWidth: 200, - maxHeight: 200, - autoRotate: true, - debug: false, - mimeType: 'image/png' - }; - const configHQ = { - quality: 1, - maxWidth: 800, - maxHeight: 800, - autoRotate: true, - debug: false, - mimeType: 'image/png' - }; if (file) { //if you cancel the image uploaded, the event is dispached and the file is null - const { onChange } = this.props; - const resizedBlob = await this.resizeImage(file, configLQ); - const blobHQ = await this.resizeImage(file, configHQ); - onChange(resizedBlob, file.name, blobHQ); + await this.resizeImage(file); } }; render() { const { intl } = this.props; - if (isCordova()) { - requestCvaPermissions(); - } return ( -
- - +
+ {isAndroid() ? ( +
+ +
+ ) : ( +
+ + +
+ )}
); } diff --git a/src/components/UI/InputImage/InputImage.css b/src/components/UI/InputImage/InputImage.css index 1eda393b9..56e4b408f 100644 --- a/src/components/UI/InputImage/InputImage.css +++ b/src/components/UI/InputImage/InputImage.css @@ -27,3 +27,10 @@ text-overflow: ellipsis; white-space: nowrap; } + +.InputImage__button { + width: 100%; +} +.InputImage__buttonContainer { + margin-top: 6px; +} diff --git a/src/components/UI/InputImage/InputImage.test.js b/src/components/UI/InputImage/InputImage.test.js index 659b6d89a..5720749cb 100644 --- a/src/components/UI/InputImage/InputImage.test.js +++ b/src/components/UI/InputImage/InputImage.test.js @@ -3,7 +3,6 @@ import { shallowMatchSnapshot } from '../../../common/test_utils'; import { mount, shallow } from 'enzyme'; import InputImage from './InputImage.component'; -jest.mock('browser-image-resizer'); jest.mock('../../../api/api'); jest.mock('./InputImage.messages', () => { diff --git a/src/components/VoiceRecorder/VoiceRecorder.component.js b/src/components/VoiceRecorder/VoiceRecorder.component.js index bbbeb4569..598a626a2 100644 --- a/src/components/VoiceRecorder/VoiceRecorder.component.js +++ b/src/components/VoiceRecorder/VoiceRecorder.component.js @@ -7,7 +7,6 @@ import ClearIcon from '@material-ui/icons/Clear'; import LinearProgress from '@material-ui/core/LinearProgress'; import IconButton from '../UI/IconButton'; -import { isCordova, requestCvaPermissions } from '../../cordova-util'; import messages from './VoiceRecorder.messages'; import './VoiceRecorder.css'; let mediaStream = undefined; @@ -32,11 +31,6 @@ class VoiceRecorder extends Component { isRecording: false, isPlaying: false }; - componentDidMount() { - if (isCordova()) { - requestCvaPermissions(); - } - } startRecording = () => { navigator.mediaDevices diff --git a/src/cordova-util.js b/src/cordova-util.js index 7ce5965bb..b4b872742 100644 --- a/src/cordova-util.js +++ b/src/cordova-util.js @@ -275,72 +275,51 @@ export const requestCvaWritePermissions = () => { } }; -export const requestCvaPermissions = () => { - if (isCordova()) { +export const requestCvaPermissions = async () => { + if (isAndroid()) { var permissions = window.cordova.plugins.permissions; - permissions.checkPermission( - permissions.READ_EXTERNAL_STORAGE, - function(status) { - console.log('Has READ_EXTERNAL_STORAGE:', status.hasPermission); - if (!status.hasPermission) { - permissions.requestPermission( - permissions.READ_EXTERNAL_STORAGE, - function(status) { - console.log( - 'success requesting READ_EXTERNAL_STORAGE permission' - ); - }, - function(err) { - console.warn('No permissions granted for READ_EXTERNAL_STORAGE'); - } - ); - } - }, - function(err) { - console.log(err); - } - ); + const androidPermissions = { + READ_EXTERNAL_STORAGE: 'READ_EXTERNAL_STORAGE', + RECORD_AUDIO: 'RECORD_AUDIO', + READ_MEDIA_IMAGES: 'READ_MEDIA_IMAGES', + READ_MEDIA_AUDIO: 'READ_MEDIA_AUDIO' + }; - permissions.checkPermission( - permissions.RECORD_AUDIO, - function(status) { - console.log('Has RECORD_AUDIO:', status.hasPermission); - if (!status.hasPermission) { - permissions.requestPermission( - permissions.RECORD_AUDIO, + for (let permission in androidPermissions) { + try { + const { hasPermission } = await new Promise((resolve, reject) => { + permissions.checkPermission( + permissions[permission], function(status) { - console.log('success requesting RECORD_AUDIO permission'); + console.log(`Has ${permission}:`, status.hasPermission); + resolve(status); }, function(err) { - console.warn('No permissions granted for RECORD_AUDIO'); + console.log(err); + resolve({ hasPermission: false }); } ); + }); + if (!hasPermission) { + await new Promise((resolve, reject) => { + permissions.requestPermission( + permissions[permission], + function(status) { + console.log(`Success requesting ${permission} permission`); + if (!status.hasPermission) + console.log(`No permissions granted for ${permission}`); + resolve(status); + }, + function(err) { + console.log(`No permissions granted for ${permission}`); + reject(err); + } + ); + }); } - }, - function(err) { - console.log(err); + } catch (err) { + console.error(err); } - ); - - // permissions.checkPermission( - // permissions.CAMERA, - // function(status) { - // console.log('Has CAMERA:', status.hasPermission); - // if (!status.hasPermission) { - // permissions.requestPermission( - // permissions.CAMERA, - // function(status) { - // console.log('success requesting CAMERA permission'); - // }, - // function(err) { - // console.warn('No permissions granted for CAMERA'); - // } - // ); - // } - // }, - // function(err) { - // console.log(err); - // } - // ); + } } }; diff --git a/yarn.lock b/yarn.lock index 74da2beff..2f27cf243 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3974,10 +3974,10 @@ brotli@^1.2.0: dependencies: base64-js "^1.1.2" -browser-image-resizer@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browser-image-resizer/-/browser-image-resizer-1.2.0.tgz#7cbe7e3aa4c01f83f5441585208d90df40fa1696" - integrity sha512-xMiB6BnRsD6RWmkD6Av90qXY7uaAOXJPaS5D8cSazyao/bx6ENCm67XGl6BIhn1ETjK52yEs8A/atmMPp74M4A== +browser-image-resizer@^2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/browser-image-resizer/-/browser-image-resizer-2.4.1.tgz#b3332bbd6745efb72c9c63b4578b2a29f199ace3" + integrity sha512-gqrmr7+NTI9FgZVVyw/GIqwJE3MhNWaBn1R5ptu75r+/M5ncyntSMQYuYhOPonm44qQNnkGN9cnghlpd9h1Hug== browser-process-hrtime@^1.0.0: version "1.0.0"