diff --git a/.meteor/packages b/.meteor/packages
index c029bd1040c..d96e79316f8 100644
--- a/.meteor/packages
+++ b/.meteor/packages
@@ -70,7 +70,6 @@ pauli:accounts-linkedin
percolate:migrations
percolatestudio:synced-cron
raix:handlebar-helpers
-raix:push
raix:ui-dropped-event
tap:i18n
tmeasday:crypto-md5
@@ -80,3 +79,4 @@ underscorestring:underscore.string
yasaricli:slugify
yasinuslu:blaze-meta
rocketchat:colors
+raix:push@2.6.13-rc.1
diff --git a/.meteor/versions b/.meteor/versions
index a63b50c1dd4..21a0e79ba71 100644
--- a/.meteor/versions
+++ b/.meteor/versions
@@ -103,7 +103,7 @@ qnub:emojione@0.0.3
raix:eventemitter@0.1.3
raix:eventstate@0.0.2
raix:handlebar-helpers@0.2.4
-raix:push@2.6.12
+raix:push@2.6.13-rc.1
raix:ui-dropped-event@0.0.7
random@1.0.3
reactive-dict@1.1.0
diff --git a/.travis.yml b/.travis.yml
index 79c27a1a335..f51f1ee5888 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,4 +7,6 @@ before_install:
- "curl https://install.meteor.com | /bin/sh"
script:
- - meteor build --server rocket.chat ./
\ No newline at end of file
+ - meteor add rocketchat:external
+ - meteor add rocketchat:hubot
+ - meteor build --server demo.rocket.chat ./
\ No newline at end of file
diff --git a/client/lib/cordova/facebook-login.coffee b/client/lib/cordova/facebook-login.coffee
index af22e8a5ac1..5b7b7b771a7 100644
--- a/client/lib/cordova/facebook-login.coffee
+++ b/client/lib/cordova/facebook-login.coffee
@@ -16,12 +16,14 @@ Meteor.loginWithFacebookCordova = (options, callback) ->
facebookConnectPlugin.getLoginStatus (response) ->
if response.status isnt "connected"
facebookConnectPlugin.login ["public_profile", "email"], fbLoginSuccess, (error) ->
- console.log("" + error)
+ console.log('login', JSON.stringify(error), error)
+ callback(error)
else
fbLoginSuccess(response)
, (error) ->
- console.log("" + error)
+ console.log('getLoginStatus', JSON.stringify(error), error)
+ callback(error)
else
Facebook.requestCredential(options, credentialRequestCompleteCallback)
\ No newline at end of file
diff --git a/client/lib/fileUpload.coffee b/client/lib/fileUpload.coffee
new file mode 100644
index 00000000000..bbe2cd79bf1
--- /dev/null
+++ b/client/lib/fileUpload.coffee
@@ -0,0 +1,59 @@
+@fileUpload = (files) ->
+ files = [].concat files
+
+ consume = ->
+ file = files.pop()
+ if not file?
+ swal.close()
+ return
+
+ reader = new FileReader()
+ reader.onload = (event) ->
+ fileContent = event.target.result
+
+ text = ''
+
+ if file.type is 'audio'
+ text = """
+
-

-
-
{{_ "Have_your_own_chat"}}
-
← {{_ "use_menu"}}.
-
- {{ > social withParagraph }}
-
-
{{_ "Get_to_know_the_team" }}
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
-
-
+ {{{body}}}
-
diff --git a/client/views/app/message.coffee b/client/views/app/message.coffee
index 63b4333bfe0..3e369c23dae 100644
--- a/client/views/app/message.coffee
+++ b/client/views/app/message.coffee
@@ -19,9 +19,9 @@ Template.message.helpers
when 'r' then t('Room_name_changed', { room_name: this.msg, user_by: this.u.username })
when 'au' then t('User_added_by', { user_added: this.msg, user_by: this.u.username })
when 'ru' then t('User_removed_by', { user_removed: this.msg, user_by: this.u.username })
- when 'ul' then tr('User_left', { context: this.u.gender }, { user_left: this.u.username })
+ when 'ul' then t('User_left', { user_left: this.u.username })
when 'nu' then t('User_added', { user_added: this.u.username })
- when 'uj' then tr('User_joined_channel', { context: this.u.gender }, { user: this.u.username })
+ when 'uj' then t('User_joined_channel', { user: this.u.username })
when 'wm' then t('Welcome', { user: this.u.username })
when 'rtc' then RocketChat.callbacks.run 'renderRtcMessage', this
else
@@ -59,7 +59,7 @@ Template.message.onViewRendered = (context) ->
ul = lastNode.parentElement
wrapper = ul.parentElement
- if context.urls?.length > 0 and Template.oembedBaseWidget?
+ if context.urls?.length > 0 and Template.oembedBaseWidget? and RocketChat.settings.get 'API_Embed'
for item in context.urls
do (item) ->
urlNode = lastNode.querySelector('.body a[href="'+item.url+'"]')
diff --git a/client/views/app/messagePopup.coffee b/client/views/app/messagePopup.coffee
index be543f423b7..a9a12d6eb42 100644
--- a/client/views/app/messagePopup.coffee
+++ b/client/views/app/messagePopup.coffee
@@ -118,7 +118,7 @@ Template.messagePopup.onCreated ->
firstPartValue = value.substr 0, caret
lastPartValue = value.substr caret
- firstPartValue = firstPartValue.replace(template.selectorRegex, template.prefix + this.getValue(template.value.curValue, template.data.collection) + template.suffix)
+ firstPartValue = firstPartValue.replace(template.selectorRegex, template.prefix + this.getValue(template.value.curValue, template.data.collection, firstPartValue) + template.suffix)
template.input.value = firstPartValue + lastPartValue
diff --git a/client/views/app/messagePopupConfig.coffee b/client/views/app/messagePopupConfig.coffee
index bb0713c7488..d9663b1642b 100644
--- a/client/views/app/messagePopupConfig.coffee
+++ b/client/views/app/messagePopupConfig.coffee
@@ -21,11 +21,19 @@ Template.messagePopupConfig.helpers
items.unshift all
return items
- getValue: (_id, collection) ->
+ getValue: (_id, collection, firstPartValue) ->
if _id is '@all'
- return 'all'
+ if firstPartValue.indexOf(' ') > -1
+ return 'all'
+
+ return 'all:'
+
+ username = collection.findOne(_id)?.username
+
+ if firstPartValue.indexOf(' ') > -1
+ return username
- return collection.findOne(_id)?.username
+ return username + ':'
return config
diff --git a/client/views/app/room.coffee b/client/views/app/room.coffee
index c8d5b2a1b97..555e2edbec1 100644
--- a/client/views/app/room.coffee
+++ b/client/views/app/room.coffee
@@ -295,6 +295,9 @@ Template.room.helpers
canJoin: ->
return !! ChatRoom.findOne { _id: @_id, t: 'c' }
+ canRecordAudio: ->
+ return navigator.getUserMedia? or navigator.webkitGetUserMedia?
+
Template.room.events
@@ -353,20 +356,15 @@ Template.room.events
return
items = e.originalEvent.clipboardData.items
+ files = []
for item in items
if item.kind is 'file' and item.type.indexOf('image/') isnt -1
e.preventDefault()
+ files.push
+ file: item.getAsFile()
+ name: 'Clipboard'
- blob = item.getAsFile()
-
- newFile = new (FS.File)(blob)
- newFile.name('Clipboard')
- newFile.rid = Session.get('openedRoom')
- newFile.recId = Random.id()
- newFile.userId = Meteor.userId()
- Files.insert newFile, (error, fileObj) ->
- unless error
- toastr.success 'Upload from clipboard succeeded!'
+ fileUpload files
'keydown .input-message': (event) ->
Template.instance().chatMessages.keydown(@_id, event, Template.instance())
@@ -551,14 +549,43 @@ Template.room.events
'dropped .dropzone-overlay': (e) ->
e.currentTarget.parentNode.classList.remove 'over'
+ files = []
FS?.Utility?.eachFile e, (file) ->
- newFile = new (FS.File)(file)
- newFile.rid = Session.get('openedRoom')
- newFile.recId = Random.id()
- newFile.userId = Meteor.userId()
- Files.insert newFile, (error, fileObj) ->
- unless error
- toastr.success 'Upload succeeded!'
+ files.push
+ file: file
+ name: file.name
+
+ fileUpload files
+
+ 'change .message-form input[type=file]': (event, template) ->
+ e = event.originalEvent or event
+ files = e.target.files
+ if not files or files.length is 0
+ files = e.dataTransfer?.files or []
+
+ filesToUpload = []
+ for file in files
+ filesToUpload.push
+ file: file
+ name: file.name
+
+ fileUpload filesToUpload
+
+ 'click .message-form .mic': (e, t) ->
+ AudioRecorder.start ->
+ t.$('.stop-mic').removeClass('hidden')
+ t.$('.mic').addClass('hidden')
+
+ 'click .message-form .stop-mic': (e, t) ->
+ AudioRecorder.stop (blob) ->
+ fileUpload [{
+ file: blob
+ type: 'audio'
+ name: 'Audio record'
+ }]
+
+ t.$('.stop-mic').addClass('hidden')
+ t.$('.mic').removeClass('hidden')
'click .deactivate': ->
username = Session.get('showUserInfo')
diff --git a/client/views/app/room.html b/client/views/app/room.html
index e21d2fb007b..ca1a46c1f72 100644
--- a/client/views/app/room.html
+++ b/client/views/app/room.html
@@ -45,10 +45,24 @@