diff --git a/index.js b/index.js
index 490898ee..7965335f 100644
--- a/index.js
+++ b/index.js
@@ -86,10 +86,10 @@ function bytesToHumanSize(bytes) {
return '0 Bytes';
}
- var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
- var bucket = Math.floor(Math.log2(bytes) / 10) | 0;
+ var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
+ var bucket = Math.min(Math.floor(Math.log2(bytes) / 10) | 0, sizes.length-1);
var count = bytes / Math.pow(1024, bucket);
- var round = bucket > 0 ? (count < 10 ? 2 : (count < 100 ? 1 : 0)) : 0;
+ var round = bucket > 0 ? (count < 3 ? 2 : (count < 30 ? 1 : 0)) : 0;
return count.toFixed(round) + ' ' + sizes[bucket];
}
@@ -673,26 +673,6 @@ class LetterTile extends React.PureComponent {
}
/* END Lettertile */
-/* File uload spinner with a cancel inside */
-class FileUploadProgress extends React.PureComponent {
- constructor(props) {
- super(props);
- }
-
- render() {
- return (
-
-
- {this.props.progress < 0.999 ?
-
close cancel
- :
-
finishing...
- }
-
- );
- }
-}
-
/* BEGIN In-place text editor. Shows text with an icon
* which toggles it into an input field */
class InPlaceEdit extends React.Component {
@@ -3320,8 +3300,17 @@ class ChatMessage extends React.Component {
constructor(props) {
super(props);
+ this.state = {
+ progress: 0
+ };
+
+ if (props.uploader) {
+ props.uploader.onProgress = this.handleProgress.bind(this);
+ }
+
this.handlePreviewImage = this.handlePreviewImage.bind(this);
this.handleContextClick = this.handleContextClick.bind(this);
+ this.handleCancelUpload = this.handleCancelUpload.bind(this);
}
handlePreviewImage(e) {
@@ -3342,6 +3331,14 @@ class ChatMessage extends React.Component {
this.props.showContextMenu({ seq: this.props.seq, y: e.pageY, x: e.pageX });
}
+ handleProgress(ratio) {
+ this.setState({progress: ratio});
+ }
+
+ handleCancelUpload() {
+ this.props.uploader.cancel();
+ }
+
render() {
var elementKey = 0;
@@ -3380,8 +3377,8 @@ class ChatMessage extends React.Component {
downloadUrl={Drafty.getDownloadUrl(att)}
filename={att.name} uploader={Drafty.isUploading(att)}
mimetype={att.mime} size={Drafty.getEntitySize(att)}
- progress={this.props.progress}
- onCancelUpload={this.props.onCancelUpload}
+ progress={this.state.progress}
+ onCancelUpload={this.handleCancelUpload}
onError={this.props.onError}
key={i} />);
}, this);
@@ -3403,7 +3400,6 @@ class ChatMessage extends React.Component {
{content}
{attachments}
@@ -3420,37 +3416,6 @@ class ChatMessage extends React.Component {
}
};
-class MessageUploader extends React.PureComponent {
- render() {
- var sideClass = this.props.sequence + " right";
- var bubbleClass = "bubble tip";
-
- var attachments = [
-
- ];
-
- return (
-
-
-
- );
- }
-};
-
-
/* Received/read indicator */
class ReceivedMarker extends React.PureComponent {
render() {
@@ -3477,6 +3442,22 @@ class ReceivedMarker extends React.PureComponent {
}
};
+/* File uload/download progress indicator with a cancel inside */
+class FileProgress extends React.PureComponent {
+ render() {
+ return (
+
+
+ {this.props.progress < 0.999 ?
+
close cancel
+ :
+
finishing...
+ }
+
+ );
+ }
+}
+
class Attachment extends React.Component {
constructor(props) {
super(props);
@@ -3493,16 +3474,15 @@ class Attachment extends React.Component {
downloadFile(url, filename, mimetype) {
var downloader = Tinode.getLargeFileHelper();
this.setState({downloader: downloader});
- var instance = this;
- downloader.download(url, filename, mimetype, function(e) {
- instance.setState({progress: e.loaded / instance.props.size});
- }).then(function() {
- instance.setState({downloader: null, progress: 0});
- }).catch(function(err) {
+ downloader.download(url, filename, mimetype, (loaded) => {
+ this.setState({progress: loaded / this.props.size});
+ }).then(() => {
+ this.setState({downloader: null, progress: 0});
+ }).catch((err) => {
if (err) {
- instance.props.onError("Error downloading file: " + err.message, "err");
+ this.props.onError("Error downloading file: " + err.message, "err");
}
- instance.setState({downloader: null, progress: 0});
+ this.setState({downloader: null, progress: 0});
});
}
@@ -3538,14 +3518,14 @@ class Attachment extends React.Component {
url = this.props.downloadUrl;
helperFunc = null;
}
- var progress = this.props.uploader ? this.props.progress : this.state.progress;
return (
insert_drive_file
{filename} {size}
{this.props.uploader || this.state.downloader ?
-
+
:
file_download save
@@ -3563,7 +3543,6 @@ class MessagesView extends React.Component {
this.state = {
messages: [],
- uploadProgress: 0,
onlineSubs: [],
topic: '',
title: '',
@@ -3665,8 +3644,7 @@ class MessagesView extends React.Component {
onlineSubs: subs,
topic: props.topic,
imagePreview: null,
- scrollPosition: 0,
- uploadProgress: 0,
+ scrollPosition: 0
});
tryToResubscribe = true;
@@ -3796,10 +3774,13 @@ class MessagesView extends React.Component {
if (topic.isNewMessage(msg.seq)) {
newState.scrollPosition = 0;
}
+
// Aknowledge all messages, including own messges.
- this.props.readTimerHandler(function() {
- topic.noteRead(msg.seq);
- });
+ if (topic.msgStatus(msg) != Tinode.MESSAGE_STATUS_PENDING) {
+ this.props.readTimerHandler(() => {
+ topic.noteRead(msg.seq);
+ });
+ }
this.props.onData(msg);
}
@@ -3888,7 +3869,7 @@ class MessagesView extends React.Component {
previousFrom = msg.from;
var isReply = !(msg.from === this.props.myUserId);
- var msgDeliveryStatus = topic.msgStatus(msg);
+ var deliveryStatus = topic.msgStatus(msg);
var userName, userAvatar, userFrom, chatBoxClass;
if (groupTopic) {
@@ -3907,7 +3888,7 @@ class MessagesView extends React.Component {
{
+ this.receivedTimer = undefined;
+ topic.noteRecv(data.seq);
+ }, RECEIVED_DELAY);
+ }
}
/* Fnd topic: find contacts by tokens */
@@ -4697,11 +4681,15 @@ class AppView extends React.Component {
handleSendMessage(msg, promise, uploader) {
let topic = Tinode.getTopic(this.state.topicSelected);
msg = topic.createMessage(Drafty.parse(msg) || msg);
+ msg._uploader = uploader;
+ promise.catch((err) => {
+ this.handleError(err.message, "err");
+ });
topic.publishDraft(msg, promise)
.catch((err) => {
this.handleError(err.message, "err");
- });
+ });
}
// User chose a Sign Up menu item.