Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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: 3 additions & 1 deletion packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -1262,8 +1262,10 @@
"Message_Attachments": "Message Attachments",
"Message_Attachments_GroupAttach": "Group Attachment Buttons",
"Message_Attachments_GroupAttachDescription": "This groups the icons under an expandable menu. Takes up less screen space.",
"Message_Audio": "Audio Message",
"Message_Audio_bitRate": "Audio Message Bit Rate",
"Message_AudioRecorderEnabled": "Audio Recorder Enabled",
"Message_AudioRecorderEnabledDescription": "Requires 'audio/wav' files to be an accepted media type within 'File Upload' settings.",
"Message_AudioRecorderEnabled_Description": "Requires 'audio/mp3' files to be an accepted media type within 'File Upload' settings.",
"Message_BadWordsFilterList": "Add Bad Words to the Blacklist",
"Message_BadWordsFilterListDescription": "Add List of Comma-separated list of bad words to filter",
"Message_DateFormat": "Date Format",
Expand Down
6 changes: 6 additions & 0 deletions packages/rocketchat-lib/server/startup/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -1177,11 +1177,17 @@ RocketChat.settings.addGroup('Message', function() {
'public': true,
i18nDescription: 'Message_Attachments_GroupAttachDescription'
});
});
this.section('Message_Audio', function() {
this.add('Message_AudioRecorderEnabled', true, {
type: 'boolean',
'public': true,
i18nDescription: 'Message_AudioRecorderEnabledDescription'
});
this.add('Message_Audio_bitRate', 32, {
type: 'int',
'public': true
});
});
this.add('Message_AllowEditing', true, {
type: 'boolean',
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.1s 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