wip: out of band avatars

This commit is contained in:
or-else
2021-07-01 14:19:28 -07:00
parent c5c08aa4f9
commit e30868c072
15 changed files with 116 additions and 42 deletions
+39 -16
View File
@@ -1,8 +1,10 @@
import React from 'react';
import LetterTile from './letter-tile.jsx';
import LoadSpinner from './load-spinner.jsx';
import { AVATAR_SIZE, MAX_EXTERN_ATTACHMENT_SIZE } from '../config.js';
import { AVATAR_SIZE, IMAGE_PREVIEW_DIM, MAX_AVATAR_BYTES, MAX_EXTERN_ATTACHMENT_SIZE,
MAX_INBAND_ATTACHMENT_SIZE } from '../config.js';
import { imageScaled, blobToBase64, makeImageDataUrl } from '../lib/blob-helpers.js';
export default class AvatarUpload extends React.Component {
@@ -10,7 +12,8 @@ export default class AvatarUpload extends React.Component {
super(props);
this.state = {
dataUrl: props.avatar
dataUrl: props.avatar,
uploading: false
};
this.handleFileUpload = this.handleFileUpload.bind(this);
@@ -18,25 +21,44 @@ export default class AvatarUpload extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.avatar != prevProps.avatar) {
this.setState({dataUrl: this.props.avatar})
this.setState({dataUrl: this.props.avatar});
}
}
handleFileUpload(e) {
imageScaled(e.target.files[0], AVATAR_SIZE, AVATAR_SIZE, MAX_EXTERN_ATTACHMENT_SIZE, true,
// Image successfully scaled and converted.
(mime, blob) => {
// Convert blob to base64-encoded bits.
blobToBase64(blob, (unused, base64bits) => {
const du = makeImageDataUrl({data: base64bits, type: mime});
this.setState({dataUrl: du});
this.props.onImageChanged(du);
const image = e.target.files[0];
if (image.size > MAX_AVATAR_BYTES) {
// Too large to send inband - uploading out of band and sending as a link.
const uploader = this.props.tinode.getLargeFileHelper();
if (!uploader) {
this.props.onError(this.props.intl.formatMessage(messages.cannot_initiate_upload));
return;
}
uploader.upload(image)
.then(() => {})
.catch((err) => {
this.props.onError(err, 'err');
})
.finally(() => {
this.setState({uploading: false});
});
},
// Failure
(err) => {
this.props.onError(err, 'err');
});
} else {
imageScaled(image, AVATAR_SIZE, AVATAR_SIZE, MAX_EXTERN_ATTACHMENT_SIZE, true,
// Image successfully scaled and converted.
(mime, blob) => {
// Convert blob to base64-encoded bits.
blobToBase64(blob, (unused, base64bits) => {
const du = makeImageDataUrl({data: base64bits, type: mime});
this.setState({dataUrl: du});
this.props.onImageChanged(du);
});
},
// Failure
(err) => {
this.props.onError(err, 'err');
});
}
// Clear the value so the same file can be uploaded again.
e.target.value = '';
}
@@ -71,6 +93,7 @@ export default class AvatarUpload extends React.Component {
<label htmlFor={randId} className="round">
<i className="material-icons">file_upload</i>
</label>}
<LoadSpinner show={this.state.uploading} large={true} clear={true} centered={true} />
</div>
);
}
+3 -1
View File
@@ -2,7 +2,9 @@ import React from 'react';
export default class LoadSpinner extends React.PureComponent {
render() {
const className = 'load-spinner-box' + (this.props.large ? ' large' : '')
+ (this.props.clear ? ' clear' : '') + (this.props.centered ? ' centered' : '');
return (this.props.show ?
<div className="load-spinner-box"><div className="loader-spinner"></div></div> : null);
<div className={className}><div className="loader-spinner"></div></div> : null);
}
}
+1
View File
@@ -87,6 +87,7 @@ export default class NewTopicGroup extends React.PureComponent {
}</FormattedMessage>
</div>
<AvatarUpload
tinode={this.props.tinode}
onError={this.props.onError}
onImageChanged={this.handleImageChanged} />
</div>