Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NEW] Audio recording as mp3 and better ui for recording #9726

Merged
merged 13 commits into from
Mar 15, 2018
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ packages/rocketchat-videobridge/client/public/external_api.js
packages/rocketchat-theme/client/vendor/
private/moment-locales/
public/livechat/
public/recorderWorker.js
public/mp3-realtime-worker.js
public/lame.min.js
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,13 @@
"iconv-lite": "^0.4.19",
"image-size": "^0.6.2",
"imap": "^0.8.19",
"ip-range-check": "0.0.2",
"jquery": "^3.2.1",
"jschardet": "1.6.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove these duplicated lines?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

"ip-range-check": "^0.0.2",
"jquery": "^3.3.1",
"jschardet": "^1.6.0",
"lamejs": "^1.2.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you still using the import?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the idea was to use this instead of including the file. But per DM struggling to get the import to work in the worker.

So need to figure out how to serve the file out of the npm package

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that was the purpose but I am not able to serve it from node_modules
I have removed the dependency for now.

"ldapjs": "^1.0.2",
"less": "https://github.com/meteor/less.js/tarball/8130849eb3d7f0ecf0ca8d0af7c4207b0442e3f6",
"less-plugin-autoprefix": "^1.5.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,26 @@
& .rc-input__icon-svg--plus {
transition: transform 0.2s linear;
}

&.cross {
color: red;
}

&.loading {
cursor: pointer;
display: none;
&.active {
display: flex;
}
}

&.mic {
display: none;
&.active {
display: flex;
}
}

}

&__action-menu {
Expand All @@ -151,6 +171,33 @@
& [data-small] {
display: none;
}

&__audio-recording {
display: none;
position: relative;
z-index: -1;
&.active{
display: flex;
z-index: 2;
}
}

&__audio-message{
&.hidden{
z-index: -1;
}
}

&__timer-box{
display: flex;
width: 50px;
}

&__timer-dot{
font-size: 1.5em;
color: #d60000;
line-height: 0.8em;
}
}

@media (width <= 500px) {
Expand Down
24 changes: 24 additions & 0 deletions packages/rocketchat-ui-message/client/messageBox.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
{{> icon block="rc-input__icon-svg" icon="send"}}
</div>
{{else}}
{{> messageBox__audioMessage}}
{{> messageBox__actions}}
{{/unless}}
{{# messageBox__actionsSmall}}
Expand Down Expand Up @@ -90,6 +91,29 @@
{{/if}}
</div>
</template>
<template name="messageBox__audioMessage">
<div class="rc-message-box__audio-recording">
<div class="rc-message-box__icon cross js-audio-message-cross">
<img src="/images/circle-cross.svg">
</div>
<div class="rc-message-box__timer-box">
<p class="rc-message-box__timer-dot">&#8226;&nbsp;</p>
<span class="rc-message-box__timer"> 00:00</span>
</div>
<div class="rc-message-box__icon check js-audio-message-check">
<img src="/images/circle-check.svg">
</div>
</div>
<div class="rc-message-box__audio-message">
<div class="rc-message-box__icon mic active js-audio-message-record">
{{> icon block="rc-input__icon-svg" icon="mic"}}
</div>
<div class="rc-message-box__icon loading js-audio-message-loading">
<img class="rc-input__icon-svg" src="/images/loading.svg">
</div>
</div>
</template>

<template name="messageBox__actionsSmall">
<div class="js-message-actions rc-message-box__action-label" data-small>
{{#each actions }}
Expand Down
166 changes: 164 additions & 2 deletions packages/rocketchat-ui-message/client/messageBox.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/* globals fileUpload KonchatNotification chatMessages popover isRtl */
/* globals fileUpload KonchatNotification chatMessages popover isRtl AudioRecorder chatMessages fileUploadHandler*/
import toastr from 'toastr';
import moment from 'moment';
import _ from 'underscore';

let audioMessageIntervalId;

function katexSyntax() {
if (RocketChat.katex.katex_enabled()) {
Expand Down Expand Up @@ -269,6 +272,9 @@ Template.messageBox.helpers({
},
isEmojiEnable() {
return RocketChat.getUserPreference(Meteor.user(), 'useEmojis');
},
isAudioMessageAllowed() {
return RocketChat.settings.get('FileUpload_Enabled') && RocketChat.settings.get('Message_AudioRecorderEnabled') && (!RocketChat.settings.get('FileUpload_MediaTypeWhiteList'));
}
});

Expand Down Expand Up @@ -452,7 +458,7 @@ Template.messageBox.events({
}
],
mousePosition: {
x: document.querySelector('.rc-message-box__textarea').getBoundingClientRect().right + 10,
x: document.querySelector('.rc-message-box__textarea').getBoundingClientRect().right + 40,
y: document.querySelector('.rc-message-box__textarea').getBoundingClientRect().top
},
customCSSProperties: {
Expand All @@ -465,6 +471,162 @@ Template.messageBox.events({
};

popover.open(config);
},
'click .js-audio-message-record'(event) {
event.preventDefault();
const icon = document.querySelector('.rc-message-box__audio-message');
const timer = document.querySelector('.rc-message-box__timer');
const timer_box = document.querySelector('.rc-message-box__audio-recording');

chatMessages[RocketChat.openedRoom].recording = true;
AudioRecorder.start(function() {
const startTime = new Date;
timer.innerHTML = '00:00';
audioMessageIntervalId = setInterval(()=> {
const now = new Date;
const distance = now-startTime;
let minutes = Math.floor(distance / (1000 * 60));
let seconds = Math.floor((distance % (1000 * 60)) / 1000);
if (minutes < 10) { minutes = `0${ minutes }`; }
if (seconds < 10) { seconds = `0${ seconds }`; }
timer.innerHTML = `${ minutes }:${ seconds }`;
}, 1000);

icon.classList.add('hidden');
timer_box.classList.add('active');
});
},
'click .js-audio-message-cross'(event) {
event.preventDefault();
const icon = document.querySelector('.rc-message-box__audio-message');
const timer = document.querySelector('.rc-message-box__timer');
const timer_box = document.querySelector('.rc-message-box__audio-recording');

timer_box.classList.remove('active');
icon.classList.remove('hidden');
timer.innerHTML = '00:00';
if (audioMessageIntervalId) {
clearInterval(audioMessageIntervalId);
}

AudioRecorder.stop();
chatMessages[RocketChat.openedRoom].recording = false;
},
'click .js-audio-message-check'(event) {
event.preventDefault();
const icon = document.querySelector('.rc-message-box__audio-message');
const timer = document.querySelector('.rc-message-box__timer');
const timer_box = document.querySelector('.rc-message-box__audio-recording');
const loader = document.querySelector('.js-audio-message-loading');
const mic = document.querySelector('.js-audio-message-record');

icon.classList.remove('hidden');
timer_box.classList.remove('active');
mic.classList.remove('active');
loader.classList.add('active');

timer.innerHTML = '00:00';
if (audioMessageIntervalId) {
clearInterval(audioMessageIntervalId);
}

chatMessages[RocketChat.openedRoom].recording = false;
AudioRecorder.stop(function(blob) {

loader.classList.remove('active');
mic.classList.add('active');
const roomId = Session.get('openedRoom');
const record = {
name: `${ TAPi18n.__('Audio record') }.mp3`,
size: blob.size,
type: 'audio/mp3',
rid: roomId,
description: ''
};
const upload = fileUploadHandler('Uploads', record, blob);
let uploading = Session.get('uploading') || [];
uploading.push({
id: upload.id,
name: upload.getFileName(),
percentage: 0
});
Session.set('uploading', uploading);
upload.onProgress = function(progress) {
uploading = Session.get('uploading');

const item = _.findWhere(uploading, {id: upload.id});
if (item != null) {
item.percentage = Math.round(progress * 100) || 0;
return Session.set('uploading', uploading);
}
};

upload.start(function(error, file, storage) {
if (error) {
let uploading = Session.get('uploading');
if (!Array.isArray(uploading)) {
uploading = [];
}

const item = _.findWhere(uploading, { id: upload.id });

if (_.isObject(item)) {
item.error = error.message;
item.percentage = 0;
} else {
uploading.push({
error: error.error,
percentage: 0
});
}

Session.set('uploading', uploading);
return;
}


if (file) {
Meteor.call('sendFileMessage', roomId, storage, file, () => {
Meteor.setTimeout(() => {
const uploading = Session.get('uploading');
if (uploading !== null) {
const item = _.findWhere(uploading, {
id: upload.id
});
return Session.set('uploading', _.without(uploading, item));
}
}, 2000);
});
}
});

Tracker.autorun(function(c) {
const cancel = Session.get(`uploading-cancel-${ upload.id }`);
if (cancel) {
let item;
upload.stop();
c.stop();

uploading = Session.get('uploading');
if (uploading != null) {
item = _.findWhere(uploading, {id: upload.id});
if (item != null) {
item.percentage = 0;
}
Session.set('uploading', uploading);
}

return Meteor.setTimeout(function() {
uploading = Session.get('uploading');
if (uploading != null) {
item = _.findWhere(uploading, {id: upload.id});
return Session.set('uploading', _.without(uploading, item));
}
}, 1000);
}
});
});
return false;
}
});

Expand Down
36 changes: 1 addition & 35 deletions packages/rocketchat-ui-message/startup/messageBoxActions.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* globals fileUpload chatMessages AudioRecorder device popover modal */
/* globals fileUpload device modal */

import mime from 'mime-type/with-db';
import {VRecDialog} from 'meteor/rocketchat:ui-vrecord';
Expand All @@ -12,40 +12,6 @@ RocketChat.messageBox.actions.add('Create_new', 'Video_message', {
}
});

RocketChat.messageBox.actions.add('Create_new', 'Audio_message', {
id: 'audio-message',
icon: 'mic',
condition: () => (navigator.getUserMedia || navigator.webkitGetUserMedia) && RocketChat.settings.get('FileUpload_Enabled') && RocketChat.settings.get('Message_AudioRecorderEnabled') && (!RocketChat.settings.get('FileUpload_MediaTypeWhiteList') || RocketChat.settings.get('FileUpload_MediaTypeWhiteList').match(/audio\/wav|audio\/\*/i)),
action({event, element}) {
event.preventDefault();
const icon = element.querySelector('.rc-icon');

if (chatMessages[RocketChat.openedRoom].recording) {
AudioRecorder.stop(function(blob) {
popover.close();
icon.style.color = '';
icon.classList.remove('pulse');
chatMessages[RocketChat.openedRoom].recording = false;
fileUpload([
{
file: blob,
type: 'audio',
name: `${ TAPi18n.__('Audio record') }.wav`
}
]);
});
return false;
}

chatMessages[RocketChat.openedRoom].recording = true;
AudioRecorder.start(function() {
icon.classList.add('pulse');
icon.style.color = 'red';
});
}
});


RocketChat.messageBox.actions.add('Add_files_from', 'Computer', {
id: 'file-upload',
icon: 'computer',
Expand Down
Loading