audio messages are correctly formed and sent

This commit is contained in:
or-else
2022-03-11 15:42:07 -08:00
parent 038f62d535
commit 609d3e3a9f
23 changed files with 4382 additions and 6395 deletions
+1 -1
View File
@@ -186,7 +186,7 @@ export function fileToBase64(file) {
export function blobToBase64(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onerror = (evt) => {
reader.onerror = _ => {
reject(reader.error);
};
reader.onload = () => {
+1 -1
View File
@@ -1,6 +1,6 @@
// Odds and ends
import Tinode from 'tinode-sdk';
import { Tinode } from 'tinode-sdk';
// Make shortcut icon appear with a green dot + show unread count in title.
export function updateFavicon(count) {
+1 -1
View File
@@ -2,7 +2,7 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import Tinode from 'tinode-sdk';
import { Tinode } from 'tinode-sdk';
import { APP_NAME, LINK_CONTACT_US, LINK_PRIVACY_POLICY, LINK_TERMS_OF_SERVICE } from '../config.js';
+1 -1
View File
@@ -2,7 +2,7 @@
import React from 'react';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import Tinode from 'tinode-sdk';
import { Tinode } from 'tinode-sdk';
import AvatarUpload from '../widgets/avatar-upload.jsx';
import BadgeList from '../widgets/badge-list.jsx';
+1 -1
View File
@@ -2,7 +2,7 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import Tinode from 'tinode-sdk';
import { Tinode } from 'tinode-sdk';
import { APP_NAME } from '../config.js';
+45 -5
View File
@@ -3,8 +3,7 @@
import React from 'react';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import Tinode from 'tinode-sdk';
const Drafty = Tinode.Drafty;
import { Drafty, Tinode } from 'tinode-sdk';
import ChatMessage from '../widgets/chat-message.jsx';
import ContactBadges from '../widgets/contact-badges.jsx';
@@ -92,6 +91,7 @@ class MessagesView extends React.Component {
this.retrySend = this.retrySend.bind(this);
this.sendImageAttachment = this.sendImageAttachment.bind(this);
this.sendFileAttachment = this.sendFileAttachment.bind(this);
this.sendAudioAttachment = this.sendAudioAttachment.bind(this);
this.sendKeyPress = this.sendKeyPress.bind(this);
this.subscribe = this.subscribe.bind(this);
this.handleScrollReference = this.handleScrollReference.bind(this);
@@ -189,7 +189,7 @@ class MessagesView extends React.Component {
if (topic && ((this.state.topic != prevState.topic) || !prevProps.ready)) {
if (topic._new) {
console.log('Fetching new topic description');
console.log('DEBUG: Fetching new topic description');
// topic.getMeta(topic.startMetaQuery().withDesc().build());
} else {
this.subscribe(topic);
@@ -744,6 +744,10 @@ class MessagesView extends React.Component {
if (file.size > maxInbandAttachmentSize) {
// 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;
}
const uploadCompletionPromise = uploader.upload(file);
const msg = Drafty.attachFile(null, {
mime: file.type,
@@ -761,7 +765,7 @@ class MessagesView extends React.Component {
}
}
// handleAttachFile method is called when [Attach file] button is clicked.
// handleAttachFile method is called when [Attach file] button is clicked: launch attachment preview.
handleAttachFile(file) {
const maxExternAttachmentSize = this.props.tinode.getServerLimit('maxFileUploadSize', MAX_EXTERN_ATTACHMENT_SIZE);
@@ -846,7 +850,7 @@ class MessagesView extends React.Component {
});
}
// handleAttachImage method is called when [Attach image] button is clicked.
// handleAttachImage method is called when [Attach image] button is clicked: launch image preview.
handleAttachImage(file) {
const maxExternAttachmentSize = this.props.tinode.getServerLimit('maxFileUploadSize', MAX_EXTERN_ATTACHMENT_SIZE);
@@ -867,6 +871,41 @@ class MessagesView extends React.Component {
});
}
// sendAudioAttachment sends audio bits inband as Drafty message (no preview).
sendAudioAttachment(url, duration) {
// Server-provided limit reduced for base64 encoding and overhead.
const maxInbandAttachmentSize = (this.props.tinode.getServerLimit(
'maxMessageSize', MAX_INBAND_ATTACHMENT_SIZE) * 0.75 - 1024) | 0;
fetch(url).then(result => {
return result.blob();
}).then(blob => {
if (blob.size > maxInbandAttachmentSize) {
// 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;
}
const uploadCompletionPromise = uploader.upload(blob);
const msg = Drafty.appendAudio(null, {
mime: blob.type,
size: blob.size,
duration: duration,
urlPromise: uploadCompletionPromise
});
// Pass data and the uploader to the TinodeWeb.
this.sendMessage(msg, uploadCompletionPromise, uploader);
} else {
// Small enough to send inband.
blobToBase64(blob)
.then(b64 => {
this.sendMessage(Drafty.appendAudio(null, {mime: b64.mime, data: b64.bits, duration: duration}))
})
.catch(err => {this.props.onError(err)});
}
});
}
handleCancelUpload(seq, uploader) {
const topic = this.props.tinode.getTopic(this.state.topic);
const found = topic.findMessage(seq);
@@ -1176,6 +1215,7 @@ class MessagesView extends React.Component {
onSendMessage={this.sendMessage}
onAttachFile={this.props.forwardMessage ? null : this.handleAttachFile}
onAttachImage={this.props.forwardMessage ? null : this.handleAttachImage}
onAttachAudio={this.sendAudioAttachment}
onError={this.props.onError}
reply={this.state.reply}
onQuoteClick={this.handleQuoteClick}
+1 -1
View File
@@ -2,7 +2,7 @@
import React from 'react';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import Tinode from 'tinode-sdk';
import { Tinode } from 'tinode-sdk';
import ContactList from '../widgets/contact-list.jsx';
import NewTopicById from '../widgets/new-topic-by-id.jsx';
+7 -12
View File
@@ -6,7 +6,7 @@ import { initializeApp as firebaseInitApp } from 'firebase/app';
import { getMessaging as firebaseGetMessaging, getToken as firebaseGetToken,
deleteToken as firebaseDelToken, onMessage as firebaseOnMessage } from 'firebase/messaging';
import Tinode from 'tinode-sdk';
import { Drafty, Tinode } from 'tinode-sdk';
import Alert from '../widgets/alert.jsx';
import ContextMenu from '../widgets/context-menu.jsx';
@@ -987,7 +987,7 @@ class TinodeWeb extends React.Component {
// If there are unsent messages, try sending them now.
topic.queuedMessages((pub) => {
if (!pub._sending && topic.isSubscribed()) {
this.sendMessage(pub);
topic.publishMessage(pub);
}
});
});
@@ -1443,7 +1443,7 @@ class TinodeWeb extends React.Component {
}
// Publish spam report.
this.tinode.publish(Tinode.TOPIC_SYS, Tinode.Drafty.attachJSON(null, {
this.tinode.publish(Tinode.TOPIC_SYS, Drafty.attachJSON(null, {
'action': 'report',
'target': topicName
}));
@@ -1474,16 +1474,11 @@ class TinodeWeb extends React.Component {
this.handleSidepanelCancel();
}
const header = '➦ ' + params.userName;
const content = typeof params.content == 'string' ?
Tinode.Drafty.init(params.content) : Tinode.Drafty.forwardedContent(params.content);
const preview = Tinode.Drafty.preview(content, FORWARDED_PREVIEW_LENGTH,
undefined, params.forwarded != null);
const msg = Tinode.Drafty.append(
Tinode.Drafty.appendLineBreak(
Tinode.Drafty.mention(header, params.userFrom)),
content);
const content = typeof params.content == 'string' ? Drafty.init(params.content) : Drafty.forwardedContent(params.content);
const preview = Drafty.preview(content, FORWARDED_PREVIEW_LENGTH, undefined, params.forwarded != null);
const msg = Drafty.append(Drafty.appendLineBreak(Drafty.mention(header, params.userFrom)), content);
const msgPreview = Tinode.Drafty.quote(header, params.userFrom, preview);
const msgPreview = Drafty.quote(header, params.userFrom, preview);
const head = {
forwarded: params.topicName + ':' + params.seq
};
+1 -2
View File
@@ -3,8 +3,7 @@
import React from 'react';
import { defineMessages, injectIntl } from 'react-intl';
import { Drafty } from 'tinode-sdk';
import Tinode from 'tinode-sdk';
import { Drafty, Tinode } from 'tinode-sdk';
import Contact from './contact.jsx';
import ContactAction from './contact-action.jsx';
+6 -6
View File
@@ -237,7 +237,7 @@ class ContextMenu extends React.Component {
(() => {
const topic = this.props.tinode.getTopic(params.topicName);
if (!topic) {
console.log("Topic not found: ", params.topicName);
console.warn("Topic not found: ", params.topicName);
return;
}
return topic.delTopic(true).catch((err) => {
@@ -258,7 +258,7 @@ class ContextMenu extends React.Component {
handler: (params, errorHandler) => {
const topic = this.props.tinode.getTopic(params.topicName);
if (!topic) {
console.log("Topic not found: ", params.topicName);
console.warn("Topic not found: ", params.topicName);
return;
}
return topic.archive(true).catch((err) => {
@@ -274,7 +274,7 @@ class ContextMenu extends React.Component {
handler: (params, errorHandler) => {
const topic = this.props.tinode.getTopic(params.topicName);
if (!topic) {
console.log("Topic not found: ", params.topicName);
console.warn("Topic not found: ", params.topicName);
return;
}
return topic.archive(false).catch((err) => {
@@ -296,7 +296,7 @@ class ContextMenu extends React.Component {
handler: (params, errorHandler) => {
const topic = this.props.tinode.getTopic(params.topicName);
if (!topic || !params.user) {
console.log("Topic or user not found: '" + params.topicName + "', '" + params.user + "'");
console.warn("Topic or user not found: '" + params.topicName + "', '" + params.user + "'");
return;
}
return topic.delSubscription(params.user).catch((err) => {
@@ -378,7 +378,7 @@ class ContextMenu extends React.Component {
deleteMessages(all, hard, params, errorHandler) {
const topic = this.props.tinode.getTopic(params.topicName);
if (!topic) {
console.log("Topic not found: ", params.topicName);
console.warn("Topic not found: ", params.topicName);
return;
}
@@ -420,7 +420,7 @@ class ContextMenu extends React.Component {
topicPermissionSetter(mode, params, errorHandler) {
const topic = this.props.tinode.getTopic(params.topicName);
if (!topic) {
console.log("Topic not found", params.topicName);
console.warn("Topic not found", params.topicName);
return;
}
+1 -1
View File
@@ -2,7 +2,7 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import Tinode from 'tinode-sdk';
import { Tinode } from 'tinode-sdk';
import ContactList from './contact-list.jsx';
import SearchContacts from './search-contacts.jsx';
+1 -1
View File
@@ -1,6 +1,6 @@
import React from 'react';
import Tinode from 'tinode-sdk';
import { Tinode } from 'tinode-sdk';
import { idToColorClass } from '../lib/strformat.js';
import { sanitizeImageUrl } from '../lib/utils.js';
+1 -1
View File
@@ -2,7 +2,7 @@
import React from 'react';
import { defineMessages, injectIntl } from 'react-intl';
import Tinode from 'tinode-sdk';
import { Tinode } from 'tinode-sdk';
import { deliveryMarker } from '../lib/utils.js';
+1 -1
View File
@@ -1,6 +1,6 @@
import React from 'react';
import Tinode from 'tinode-sdk';
import { Tinode } from 'tinode-sdk';
export default class SearchContacts extends React.PureComponent {
constructor(props) {
+1 -2
View File
@@ -132,8 +132,7 @@ class SendMessage extends React.PureComponent {
handleAttachAudio(url, duration) {
this.setState({audioRec: false});
console.log("this.props.onAttachAudio", url, duration);
// this.props.onAttachAudio(url, duration);
this.props.onAttachAudio(url, duration);
}
handleSend(e) {
+1 -1
View File
@@ -3,7 +3,7 @@
import React from 'react';
import { FormattedMessage } from 'react-intl';
import Tinode from 'tinode-sdk';
import { Tinode } from 'tinode-sdk';
import AvatarCrop from './avatar-crop.jsx';
import AvatarUpload from './avatar-upload.jsx';