diff --git a/packages/rocketchat-ui/client/lib/chatMessages.coffee b/packages/rocketchat-ui/client/lib/chatMessages.coffee deleted file mode 100644 index 42ddfe99488..00000000000 --- a/packages/rocketchat-ui/client/lib/chatMessages.coffee +++ /dev/null @@ -1,425 +0,0 @@ -import moment from 'moment' -import toastr from 'toastr' - -class @ChatMessages - init: (node) -> - this.editing = {} - this.records = {} - this.messageMaxSize = RocketChat.settings.get('Message_MaxAllowedSize') - this.wrapper = $(node).find(".wrapper") - this.input = $(node).find(".input-message").get(0) - this.$input = $(this.input) - this.hasValue = new ReactiveVar false - this.bindEvents() - return - - resize: -> - dif = (if RocketChat.Layout.isEmbedded() then 0 else 60) + $(".messages-container").find("footer").outerHeight() - dif += if $(".announcement").length > 0 then 40 else 0 - $(".messages-box").css - height: "calc(100% - #{dif}px)" - - getEditingIndex: (element) -> - msgs = this.wrapper.get(0).querySelectorAll(".own:not(.system)") - index = 0 - for msg in msgs - if msg is element - return index - index++ - return -1 - - recordInputAsDraft: () -> - id = this.editing.id - - message = this.getMessageById id - record = this.records[id] || {} - draft = this.input.value - - if(draft is message.msg) - this.clearCurrentDraft() - else - record.draft = draft - this.records[id] = record - - getMessageDraft: (id) -> - return this.records[id] - - clearMessageDraft: (id) -> - delete this.records[id] - - clearCurrentDraft: () -> - this.clearMessageDraft this.editing.id - - resetToDraft: (id) -> - message = this.getMessageById id - - old_value = this.input.value - this.input.value = message.msg - - return old_value isnt message.msg - - getMessageById: (id) -> - return ChatMessage.findOne(id) - - toPrevMessage: -> - index = this.editing.index - this.editByIndex if index? then index - 1 else undefined - - toNextMessage: -> - index = this.editing.index - this.clearEditing() unless this.editByIndex index + 1 - - editByIndex: (index) -> - return false if not this.editing.element and index? - - msgs = this.wrapper.get(0).querySelectorAll(".own:not(.system)") - index = msgs.length - 1 if not index? - - return false unless msgs[index] - - element = msgs[index] - this.edit element, index - - return true - - edit: (element, index) -> - index = this.getEditingIndex(element) if not index? - - message = this.getMessageById element.getAttribute("id") - - hasPermission = RocketChat.authz.hasAtLeastOnePermission('edit-message', message.rid) - editAllowed = RocketChat.settings.get 'Message_AllowEditing' - editOwn = message?.u?._id is Meteor.userId() - - return unless hasPermission or (editAllowed and editOwn) - return if element.classList.contains("system") - - blockEditInMinutes = RocketChat.settings.get 'Message_AllowEditing_BlockEditInMinutes' - if blockEditInMinutes? and blockEditInMinutes isnt 0 - msgTs = moment(message.ts) if message.ts? - currentTsDiff = moment().diff(msgTs, 'minutes') if msgTs? - if currentTsDiff > blockEditInMinutes - return - - msg = this.getMessageDraft(message._id)?.draft - msg = message.msg unless msg? - - editingNext = this.editing.index < index - - old_input = this.input.value - - this.clearEditing() - - this.hasValue.set true - this.editing.element = element - this.editing.index = index - this.editing.id = message._id - element.classList.add("editing") - this.input.classList.add("editing") - this.$input.closest('.message-form').addClass('editing') - - this.input.focus() - if message.attachments? and message.attachments[0].description? - this.input.value = message.attachments[0].description - else - this.input.value = msg - - cursor_pos = if editingNext then 0 else -1 - this.$input.setCursorPosition(cursor_pos) - - clearEditing: -> - if this.editing.element - this.recordInputAsDraft() - - this.editing.element.classList.remove("editing") - this.input.classList.remove("editing") - this.$input.closest('.message-form').removeClass('editing') - delete this.editing.id - delete this.editing.element - delete this.editing.index - - this.input.value = this.editing.saved or "" - cursor_pos = this.editing.savedCursor ? -1 - this.$input.setCursorPosition(cursor_pos) - - this.hasValue.set this.input.value isnt '' - else - this.editing.saved = this.input.value - this.editing.savedCursor = this.input.selectionEnd - - ###* - # * @param {string} rim room ID - # * @param {Element} input DOM element - # * @param {function?} done callback - ### - send: (rid, input, done = ->) -> - if _.trim(input.value) isnt '' - readMessage.enable() - readMessage.readNow() - $('.message.first-unread').removeClass('first-unread') - - msg = input.value - msgObject = { _id: Random.id(), rid: rid, msg: msg} - - # Run to allow local encryption, and maybe other client specific actions to be run before send - RocketChat.promises.run('onClientBeforeSendMessage', msgObject).then (msgObject) => - - # checks for the final msgObject.msg size before actually sending the message - if this.isMessageTooLong(msgObject.msg) - return toastr.error t('Message_too_long') - - this.clearCurrentDraft() - if this.editing.id - this.update(this.editing.id, rid, msgObject.msg) - return - - KonchatNotification.removeRoomNotification(rid) - input.value = '' - input.updateAutogrow?() - this.hasValue.set false - this.stopTyping(rid) - - #Check if message starts with /command - if msg[0] is '/' - match = msg.match(/^\/([^\s]+)(?:\s+(.*))?$/m) - if match? - if RocketChat.slashCommands.commands[match[1]] - commandOptions = RocketChat.slashCommands.commands[match[1]] - command = match[1] - param = if match[2]? then match[2] else '' - if commandOptions.clientOnly - commandOptions.callback(command, param, msgObject) - else - Meteor.call 'slashCommand', {cmd: command, params: param, msg: msgObject }, (err, result) -> commandOptions.result?(err, result, {cmd: command, params: param, msg: msgObject }) - return - - if !RocketChat.settings.get('Message_AllowUnrecognizedSlashCommand') - invalidCommandMsg = - _id: Random.id() - rid: rid - ts: new Date - msg: TAPi18n.__('No_such_command', { command: match[1] }) - u: - username: "rocketbot" - private: true - ChatMessage.upsert { _id: invalidCommandMsg._id }, invalidCommandMsg - return - - Meteor.call 'sendMessage', msgObject - done() - - # If edited message was emptied we ask for deletion - else if this.editing.element - message = this.getMessageById this.editing.id - if message.attachments? and message.attachments[0].description? - this.update(this.editing.id, rid, '', true) - return - # Restore original message in textbox in case delete is canceled - this.resetToDraft this.editing.id - - this.confirmDeleteMsg message, done - - confirmDeleteMsg: (message, done = ->) -> - return if RocketChat.MessageTypes.isSystemMessage(message) - swal { - title: t('Are_you_sure') - text: t('You_will_not_be_able_to_recover') - type: 'warning' - showCancelButton: true - confirmButtonColor: '#DD6B55' - confirmButtonText: t('Yes_delete_it') - cancelButtonText: t('Cancel') - closeOnConfirm: false - html: false - }, => - swal - title: t('Deleted') - text: t('Your_entry_has_been_deleted') - type: 'success' - timer: 1000 - showConfirmButton: false - - if this.editing.id is message._id - this.clearEditing message - this.deleteMsg message - - this.$input.focus() - done() - - # In order to avoid issue "[Callback not called when still animating](https://github.com/t4t5/sweetalert/issues/528)" - $('.sweet-alert').addClass 'visible' - - deleteMsg: (message) -> - blockDeleteInMinutes = RocketChat.settings.get 'Message_AllowDeleting_BlockDeleteInMinutes' - if blockDeleteInMinutes? and blockDeleteInMinutes isnt 0 - msgTs = moment(message.ts) if message.ts? - currentTsDiff = moment().diff(msgTs, 'minutes') if msgTs? - if currentTsDiff > blockDeleteInMinutes - toastr.error(t('Message_deleting_blocked')) - return - - Meteor.call 'deleteMessage', { _id: message._id }, (error, result) -> - if error - return handleError(error) - - pinMsg: (message) -> - message.pinned = true - Meteor.call 'pinMessage', message, (error, result) -> - if error - return handleError(error) - - unpinMsg: (message) -> - message.pinned = false - Meteor.call 'unpinMessage', message, (error, result) -> - if error - return handleError(error) - - update: (id, rid, msg, isDescription) -> - if _.trim(msg) isnt '' or isDescription is true - Meteor.call 'updateMessage', { _id: id, msg: msg, rid: rid } - this.clearEditing() - this.stopTyping(rid) - - startTyping: (rid, input) -> - if _.trim(input.value) isnt '' - MsgTyping.start(rid) - else - MsgTyping.stop(rid) - - stopTyping: (rid) -> - MsgTyping.stop(rid) - - bindEvents: -> - if this.wrapper?.length - $(".input-message").autogrow - postGrowCallback: => - this.resize() - - tryCompletion: (input) -> - value = input.value.match(/[^\s]+$/) - if value?.length > 0 - value = value[0] - - re = new RegExp value, 'i' - - user = Meteor.users.findOne username: re - if user? - input.value = input.value.replace value, "@#{user.username} " - - keyup: (rid, event) -> - input = event.currentTarget - k = event.which - keyCodes = [ - 13, # Enter - 20, # Caps lock - 16, # Shift - 9, # Tab - 27, # Escape Key - 17, # Control Key - 91, # Windows Command Key - 19, # Pause Break - 18, # Alt Key - 93, # Right Click Point Key - 45, # Insert Key - 34, # Page Down - 35, # Page Up - 144, # Num Lock - 145 # Scroll Lock - ] - keyCodes.push i for i in [35..40] # Home, End, Arrow Keys - keyCodes.push i for i in [112..123] # F1 - F12 - - unless k in keyCodes - this.startTyping(rid, input) - - this.hasValue.set input.value isnt '' - - keydown: (rid, event) -> - sendOnEnter = Meteor.user()?.settings?.preferences?.sendOnEnter - input = event.currentTarget - $input = $(input) - k = event.which - this.resize(input) - - if k is 13 - if not sendOnEnter? || sendOnEnter is 'normal' || (sendOnEnter is 'desktop' and Meteor.Device.isDesktop()) - if not event.shiftKey and not event.ctrlKey and not event.altKey and not event.metaKey # Enter without shift/ctrl/alt - event.preventDefault() - event.stopPropagation() - this.send(rid, input) - return - else if not event.shiftKey - return input.value +='\n' - else if sendOnEnter is 'alternative' - if event.shiftKey or event.ctrlKey or event.altKey or event.metaKey # Enter with shift/ctrl/alt - event.preventDefault() - event.stopPropagation() - this.send(rid, input) - return - - - - if k is 9 # Tab - event.preventDefault() - event.stopPropagation() - @tryCompletion input - - if k is 27 # Escape - if this.editing.index? - record = this.getMessageDraft(this.editing.id) - - # If resetting did nothing then edited message is same as original - unless this.resetToDraft this.editing.id - this.clearCurrentDraft() - this.clearEditing() - - event.preventDefault() - event.stopPropagation() - return - else if k is 38 or k is 40 # Arrow Up or down - return true if event.shiftKey - - cursor_pos = input.selectionEnd - - if k is 38 # Arrow Up - if cursor_pos is 0 - this.toPrevMessage() - else if not event.altKey - return true - - this.$input.setCursorPosition(0) if event.altKey - - else # Arrow Down - if cursor_pos is input.value.length - this.toNextMessage() - else if not event.altKey - return true - - this.$input.setCursorPosition(-1) if event.altKey - - return false - - # ctrl (command) + shift + k -> clear room messages - else if k is 75 and ((navigator?.platform?.indexOf('Mac') isnt -1 and event.metaKey and event.shiftKey) or (navigator?.platform?.indexOf('Mac') is -1 and event.ctrlKey and event.shiftKey)) - RoomHistoryManager.clear rid - - valueChanged: (rid, event) -> - if this.input.value.length is 1 - this.determineInputDirection() - - determineInputDirection: () -> - this.input.dir = if this.isMessageRtl(this.input.value) then 'rtl' else 'ltr' - - # http://stackoverflow.com/a/14824756 - isMessageRtl: (message) -> - ltrChars = 'A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02B8\u0300-\u0590\u0800-\u1FFF'+'\u2C00-\uFB1C\uFDFE-\uFE6F\uFEFD-\uFFFF' - rtlChars = '\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC' - rtlDirCheck = new RegExp "^[^#{ltrChars}]*[#{rtlChars}]" - - return rtlDirCheck.test message - - isMessageTooLong: (message) -> - message?.length > this.messageMaxSize - - isEmpty: -> - return !this.hasValue.get() diff --git a/packages/rocketchat-ui/client/lib/chatMessages.js b/packages/rocketchat-ui/client/lib/chatMessages.js index 488b3a1a4da..26442775455 100644 --- a/packages/rocketchat-ui/client/lib/chatMessages.js +++ b/packages/rocketchat-ui/client/lib/chatMessages.js @@ -83,21 +83,20 @@ this.ChatMessages = class ChatMessages { } editByIndex(index) { - if (!this.editing.element && (index != null)) { return false; } + if (!this.editing.element && index) { return false; } const msgs = this.wrapper.get(0).querySelectorAll('.own:not(.system)'); - if ((index == null)) { index = msgs.length - 1; } + if (index == null) { index = msgs.length - 1; } if (!msgs[index]) { return false; } const element = msgs[index]; this.edit(element, index); - return true; } edit(element, index) { - if ((index == null)) { index = this.getEditingIndex(element); } + index = index != null ? index : this.getEditingIndex(element); const message = this.getMessageById(element.getAttribute('id')); @@ -105,7 +104,7 @@ this.ChatMessages = class ChatMessages { const editAllowed = RocketChat.settings.get('Message_AllowEditing'); const editOwn = message && message.u && message.u._id === Meteor.userId(); - if (!hasPermission && (!editAllowed || !editOwn)) { return; } + if (!hasPermission && !editAllowed || !editOwn) { return; } if (element.classList.contains('system')) { return; } const blockEditInMinutes = RocketChat.settings.get('Message_AllowEditing_BlockEditInMinutes'); @@ -121,7 +120,7 @@ this.ChatMessages = class ChatMessages { const draft = this.getMessageDraft(message._id); let msg = draft && draft.draft; - if (msg == null) { ({ msg } = message); } + msg = msg || message.msg; const editingNext = this.editing.index < index; @@ -138,7 +137,7 @@ this.ChatMessages = class ChatMessages { this.$input.closest('.message-form').addClass('editing'); this.input.focus(); - if ((message.attachments != null) && (message.attachments[0].description != null)) { + if (message.attachments && message.attachments[0].description) { this.input.value = message.attachments[0].description; } else { this.input.value = msg; @@ -175,8 +174,7 @@ this.ChatMessages = class ChatMessages { * * @param {Element} input DOM element * * @param {function?} done callback */ - send(rid, input, done) { - if (done == null) { done = function() {}; } + send(rid, input, done = function() {}) { if (_.trim(input.value) !== '') { readMessage.enable(); readMessage.readNow(); @@ -210,16 +208,16 @@ this.ChatMessages = class ChatMessages { //Check if message starts with /command if (msg[0] === '/') { const match = msg.match(/^\/([^\s]+)(?:\s+(.*))?$/m); - if (match != null) { + if (match) { let command; if (RocketChat.slashCommands.commands[match[1]]) { const commandOptions = RocketChat.slashCommands.commands[match[1]]; command = match[1]; - const param = (match[2] != null) ? match[2] : ''; + const param = match[2] || ''; if (commandOptions.clientOnly) { commandOptions.callback(command, param, msgObject); } else { - Meteor.call('slashCommand', {cmd: command, params: param, msg: msgObject }, (err, result) => typeof commandOptions.result === 'function' ? commandOptions.result(err, result, {cmd: command, params: param, msg: msgObject }) : undefined); + Meteor.call('slashCommand', {cmd: command, params: param, msg: msgObject }, (err, result) => typeof commandOptions.result === 'function' && commandOptions.result(err, result, {cmd: command, params: param, msg: msgObject })); } return; } @@ -258,8 +256,7 @@ this.ChatMessages = class ChatMessages { } } - confirmDeleteMsg(message, done) { - if (done == null) { done = function() {}; } + confirmDeleteMsg(message, done = function() {}) { if (RocketChat.MessageTypes.isSystemMessage(message)) { return; } swal({ title: t('Are_you_sure'), @@ -352,7 +349,7 @@ this.ChatMessages = class ChatMessages { } bindEvents() { - if (this.wrapper != null ? this.wrapper.length : undefined) { + if (this.wrapper && this.wrapper.length) { return $('.input-message').autogrow({ postGrowCallback: () => { return this.resize(); @@ -366,7 +363,7 @@ this.ChatMessages = class ChatMessages { if (!value) { return; } const re = new RegExp(value, 'i'); const user = Meteor.users.findOne({username: re}); - if (user != null) { + if (user) { return input.value = input.value.replace(value, `@${ user.username } `); } } @@ -411,7 +408,7 @@ this.ChatMessages = class ChatMessages { this.resize(input); if (k === 13) { - if (sendOnEnter == null || sendOnEnter === 'normal' || (sendOnEnter === 'desktop' && Meteor.Device.isDesktop())) { + if (sendOnEnter == null || sendOnEnter === 'normal' || sendOnEnter === 'desktop' && Meteor.Device.isDesktop()) { if (!event.shiftKey && !event.ctrlKey && !event.altKey && !event.metaKey) { // Enter without shift/ctrl/alt event.preventDefault(); event.stopPropagation(); @@ -452,7 +449,7 @@ this.ChatMessages = class ChatMessages { event.stopPropagation(); return; } - } else if ((k === 38) || (k === 40)) { // Arrow Up or down + } else if (k === 38 || k === 40) { // Arrow Up or down if (event.shiftKey) { return true; } const cursor_pos = input.selectionEnd; @@ -504,7 +501,7 @@ this.ChatMessages = class ChatMessages { } isMessageTooLong(message) { - return (message != null ? message.length : undefined) > this.messageMaxSize; + return message && message.length > this.messageMaxSize; } isEmpty() { diff --git a/packages/rocketchat-ui/client/lib/cordova/push.coffee b/packages/rocketchat-ui/client/lib/cordova/push.coffee deleted file mode 100644 index 50406ab9dca..00000000000 --- a/packages/rocketchat-ui/client/lib/cordova/push.coffee +++ /dev/null @@ -1,70 +0,0 @@ -if Meteor.isCordova - # Push.addListener 'token', (token) -> - # Meteor.call 'log', 'CLIENT', 'token', arguments - - # Push.addListener 'error', (err) -> - # Meteor.call 'log', 'CLIENT', 'error', arguments - # if err.type == 'apn.cordova' - # Meteor.call 'log', 'CLIENT', err.error - - # Push.addListener 'register', (evt) -> - # Meteor.call 'log', 'CLIENT', 'register', arguments - - # Push.addListener 'alert', (notification) -> - # Meteor.call 'log', 'CLIENT', 'alert', arguments - - # Push.addListener 'sound', (notification) -> - # Meteor.call 'log', 'CLIENT', 'sound', arguments - - # Push.addListener 'badge', (notification) -> - # Meteor.call 'log', 'CLIENT', 'badge', arguments - - # Push.addListener 'message', (notification) -> - # Meteor.call 'log', 'CLIENT', 'message', arguments - - Push.addListener 'startup', (notification) -> - # Meteor.call 'log', 'CLIENT', 'startup', arguments - - if notification.payload?.rid? - if notification.payload.host is Meteor.absoluteUrl() - switch notification.payload.type - when 'c' - FlowRouter.go 'channel', { name: notification.payload.name }, FlowRouter.current().queryParams - when 'p' - FlowRouter.go 'group', { name: notification.payload.name }, FlowRouter.current().queryParams - when 'd' - FlowRouter.go 'direct', { username: notification.payload.sender.username }, FlowRouter.current().queryParams - else - path = '' - switch notification.payload.type - when 'c' - path = 'channel/' + notification.payload.name - when 'p' - path = 'group/' + notification.payload.name - when 'd' - path = 'direct/' + notification.payload.sender.username - - host = notification.payload.host.replace /\/$/, '' - if Servers.serverExists(host) isnt true - return - - Servers.startServer host, path, (err, url) -> - if err? - # TODO err - return console.log err - - - Meteor.startup -> - Tracker.autorun -> - if RocketChat.settings.get('Push_enable') is true - - Push.Configure - android: - senderID: window.ANDROID_SENDER_ID - sound: true - vibrate: true - ios: - badge: true - clearBadge: true - sound: true - alert: true diff --git a/packages/rocketchat-ui/client/lib/cordova/push.js b/packages/rocketchat-ui/client/lib/cordova/push.js index 7d322604d3a..684c8cecfd8 100644 --- a/packages/rocketchat-ui/client/lib/cordova/push.js +++ b/packages/rocketchat-ui/client/lib/cordova/push.js @@ -26,7 +26,7 @@ if (Meteor.isCordova) { Push.addListener('startup', function(notification) { // Meteor.call 'log', 'CLIENT', 'startup', arguments - if ((notification.payload != null ? notification.payload.rid : undefined) != null) { + if (notification.payload && notification.payload.rid) { if (notification.payload.host === Meteor.absoluteUrl()) { switch (notification.payload.type) { case 'c': @@ -56,7 +56,7 @@ if (Meteor.isCordova) { } return Servers.startServer(host, path, function(err) { - if (err != null) { + if (err) { // TODO err return console.log(err); } @@ -67,7 +67,7 @@ if (Meteor.isCordova) { Meteor.startup(() => - Tracker.autorun(function() { + Tracker.autorun(() => { if (RocketChat.settings.get('Push_enable') === true) { Push.Configure({ diff --git a/packages/rocketchat-ui/client/lib/cordova/urls.coffee b/packages/rocketchat-ui/client/lib/cordova/urls.coffee deleted file mode 100644 index aeed6e9604b..00000000000 --- a/packages/rocketchat-ui/client/lib/cordova/urls.coffee +++ /dev/null @@ -1,14 +0,0 @@ -Meteor.startup -> - return unless Meteor.isCordova - - # Handle click events for all external URLs - $(document).on 'deviceready', -> - platform = device.platform.toLowerCase() - $(document).on 'click', (e) -> - $link = $(e.target).closest('a[href]') - return unless $link.length > 0 - url = $link.attr('href') - - if /^https?:\/\/.+/.test(url) is true - window.open url, '_system' - e.preventDefault() diff --git a/packages/rocketchat-ui/client/lib/cordova/urls.js b/packages/rocketchat-ui/client/lib/cordova/urls.js index ffac42ed71f..a11c61d810b 100644 --- a/packages/rocketchat-ui/client/lib/cordova/urls.js +++ b/packages/rocketchat-ui/client/lib/cordova/urls.js @@ -1,7 +1,7 @@ -Meteor.startup(function() { +Meteor.startup(() => { if (!Meteor.isCordova) { return; } // Handle click events for all external URLs - $(document).on('deviceready', function() { + $(document).on('deviceready', () => { // const platform = device.platform.toLowerCase(); $(document).on('click', function(e) { const $link = $(e.target).closest('a[href]'); diff --git a/packages/rocketchat-ui/client/lib/msgTyping.coffee b/packages/rocketchat-ui/client/lib/msgTyping.coffee deleted file mode 100644 index b4355443fb6..00000000000 --- a/packages/rocketchat-ui/client/lib/msgTyping.coffee +++ /dev/null @@ -1,69 +0,0 @@ -@MsgTyping = do -> - timeout = 15000 - timeouts = {} - renew = true - renewTimeout = 10000 - selfTyping = new ReactiveVar false - usersTyping = {} - dep = new Tracker.Dependency - - addStream = (room) -> - if _.isEmpty usersTyping[room]?.users - usersTyping[room] = { users: {} } - RocketChat.Notifications.onRoom room, 'typing', (username, typing) -> - unless username is Meteor.user()?.username - if typing is true - users = usersTyping[room].users - users[username] = Meteor.setTimeout -> - delete users[username] - usersTyping[room].users = users - dep.changed() - , timeout - usersTyping[room].users = users - dep.changed() - else - users = usersTyping[room].users - delete users[username] - usersTyping[room].users = users - dep.changed() - - Tracker.autorun -> - if Session.get 'openedRoom' - addStream Session.get 'openedRoom' - - start = (room) -> - return unless renew - - setTimeout -> - renew = true - , renewTimeout - - renew = false - selfTyping.set true - RocketChat.Notifications.notifyRoom room, 'typing', Meteor.user()?.username, true - clearTimeout timeouts[room] - timeouts[room] = Meteor.setTimeout -> - stop(room) - , timeout - - stop = (room) -> - renew = true - selfTyping.set false - if timeouts?[room]? - clearTimeout(timeouts[room]) - timeouts[room] = null - RocketChat.Notifications.notifyRoom room, 'typing', Meteor.user()?.username, false - - get = (room) -> - dep.depend() - unless usersTyping[room] - usersTyping[room] = { users: {} } - users = usersTyping[room].users - return _.keys(users) or [] - - return { - start: start - stop: stop - get: get - selfTyping: selfTyping - } diff --git a/packages/rocketchat-ui/client/lib/msgTyping.js b/packages/rocketchat-ui/client/lib/msgTyping.js index 73b388d93f9..c1e6adde7f8 100644 --- a/packages/rocketchat-ui/client/lib/msgTyping.js +++ b/packages/rocketchat-ui/client/lib/msgTyping.js @@ -36,7 +36,7 @@ export const MsgTyping = (function() { const stop = function(room) { renew = true; selfTyping.set(false); - if ((timeouts != null ? timeouts[room] : undefined) != null) { + if (timeouts && timeouts[room]) { clearTimeout(timeouts[room]); timeouts[room] = null; } diff --git a/packages/rocketchat-ui/client/lib/notification.coffee b/packages/rocketchat-ui/client/lib/notification.coffee deleted file mode 100644 index f3103eb7172..00000000000 --- a/packages/rocketchat-ui/client/lib/notification.coffee +++ /dev/null @@ -1,94 +0,0 @@ -# @TODO implementar 'clicar na notificacao' abre a janela do chat -@KonchatNotification = - notificationStatus: new ReactiveVar - - # notificacoes HTML5 - getDesktopPermission: -> - if window.Notification && Notification.permission != "granted" && !Meteor.settings.public.sandstorm - Notification.requestPermission (status) -> - KonchatNotification.notificationStatus.set status - if Notification.permission != status - Notification.permission = status - - notify: (notification) -> - if window.Notification && Notification.permission == "granted" - message = { rid: notification.payload?.rid, msg: notification.text, notification: true } - RocketChat.promises.run('onClientMessageReceived', message).then (message) -> - n = new Notification notification.title, - icon: notification.icon or getAvatarUrlFromUsername notification.payload.sender.username - body: _.stripTags(message.msg) - tag: notification.payload._id, - silent: true - canReply: true - - notificationDuration = (notification.duration - 0) or (Meteor.user()?.settings?.preferences?.desktopNotificationDuration - 0) or RocketChat.settings.get('Desktop_Notifications_Duration') - if notificationDuration > 0 - setTimeout ( -> n.close() ), notificationDuration * 1000 - - if notification.payload?.rid? - if n.addEventListener? - n.addEventListener 'reply', ({response}) -> - Meteor.call 'sendMessage', - _id: Random.id() - rid: notification.payload.rid - msg: response - - n.onclick = -> - this.close() - window.focus() - switch notification.payload.type - when 'd' - FlowRouter.go 'direct', { username: notification.payload.sender.username }, FlowRouter.current().queryParams - when 'c' - FlowRouter.go 'channel', { name: notification.payload.name }, FlowRouter.current().queryParams - when 'p' - FlowRouter.go 'group', { name: notification.payload.name }, FlowRouter.current().queryParams - - showDesktop: (notification) -> - if notification.payload.rid is Session.get('openedRoom') and window.document.hasFocus?() - return - - if Meteor.user().status is 'busy' or Meteor.settings.public.sandstorm? - return - - getAvatarAsPng notification.payload.sender.username, (avatarAsPng) -> - notification.icon = avatarAsPng - KonchatNotification.notify(notification) - - newMessage: (rid) -> - if not Session.equals('user_' + Meteor.userId() + '_status', 'busy') - newMessageNotification = Meteor.user()?.settings?.preferences?.newMessageNotification || 'chime' - sub = ChatSubscription.findOne({ rid: rid }, { fields: { audioNotification: 1 } }); - if sub?.audioNotification isnt 'none' - if sub?.audioNotification - $("audio##{sub.audioNotification}")?[0]?.play?() - else if newMessageNotification isnt 'none' - $("audio##{newMessageNotification}")?[0]?.play?() - - newRoom: (rid, withSound = true) -> - Tracker.nonreactive -> - newRoomSound = Session.get('newRoomSound') - if newRoomSound? - newRoomSound = _.union newRoomSound, rid - else - newRoomSound = [rid] - - Session.set('newRoomSound', newRoomSound) - - # $('.link-room-' + rid).addClass('new-room-highlight') - - removeRoomNotification: (rid) -> - Tracker.nonreactive -> - Session.set('newRoomSound', []) - - $('.link-room-' + rid).removeClass('new-room-highlight') - -Tracker.autorun -> - newRoomNotification = Meteor.user()?.settings?.preferences?.newRoomNotification || 'door' - if Session.get('newRoomSound')?.length > 0 - Tracker.nonreactive -> - if not Session.equals('user_' + Meteor.userId() + '_status', 'busy') and newRoomNotification isnt 'none' - $("audio##{newRoomNotification}")?[0]?.play?() - else - $("audio##{newRoomNotification}")?[0]?.pause?() - $("audio##{newRoomNotification}")?[0]?.currentTime = 0 diff --git a/packages/rocketchat-ui/client/lib/notification.js b/packages/rocketchat-ui/client/lib/notification.js index 94c378ab32f..095d181ba6e 100644 --- a/packages/rocketchat-ui/client/lib/notification.js +++ b/packages/rocketchat-ui/client/lib/notification.js @@ -81,7 +81,7 @@ const KonchatNotification = { const user = Meteor.user(); const newMessageNotification = user && user.settings && user.settings.preferences && user.settings.preferences.newMessageNotification || 'chime'; const sub = ChatSubscription.findOne({ rid }, { fields: { audioNotification: 1 } }); - if ((sub && sub.audioNotification) !== 'none') { + if (sub && sub.audioNotification !== 'none') { if (sub && sub.audioNotification) { const [audio] = $(`audio#${ sub.audioNotification }`); return audio && audio.play && audio.play(); @@ -93,8 +93,7 @@ const KonchatNotification = { } }, - newRoom(rid, withSound) { - if (withSound == null) { withSound = true; } + newRoom(rid/*, withSound = true*/) { Tracker.nonreactive(function() { let newRoomSound = Session.get('newRoomSound'); if (newRoomSound != null) { @@ -119,7 +118,7 @@ const KonchatNotification = { Tracker.autorun(function() { const user = Meteor.user(); const newRoomNotification = user && user.settings && user.settings.preferences && user.settings.preferences.newRoomNotification || 'door'; - if ((Session.get('newRoomSound') || []) > 0) { + if ((Session.get('newRoomSound') || []).length > 0) { Tracker.nonreactive(function() { if (!Session.equals(`user_${ Meteor.userId() }_status`, 'busy') && newRoomNotification !== 'none') { const [audio] = $(`audio#${ newRoomNotification }`); diff --git a/packages/rocketchat-ui/client/lib/readMessages.coffee b/packages/rocketchat-ui/client/lib/readMessages.coffee deleted file mode 100644 index 252c2c56cb6..00000000000 --- a/packages/rocketchat-ui/client/lib/readMessages.coffee +++ /dev/null @@ -1,179 +0,0 @@ -### DEFINITIONS -- If window loses focus user needs to scroll or click/touch some place -- On hit ESC enable read, force read of current room and remove unread mark -- When user change room disable read until user interaction -- Only read if mark of *first-unread* is visible for user or if flag *force* was passed -- Always read the opened room -- The default method *read* has a delay of 2000ms to prevent multiple reads and to user be able to see the mark -### - -# Meteor.startup -> - # window.addEventListener 'focus', -> - # readMessage.refreshUnreadMark(undefined, true) - -@readMessage = new class - debug: false - - callbacks: [] - - constructor: -> - @canReadMessage = false - - readNow: (force=false) -> - console.log '--------------' if @debug - console.log 'readMessage -> readNow init process force:', force if @debug - - self = @ - - self.refreshUnreadMark() - - if force isnt true and @canReadMessage is false - console.log 'readMessage -> readNow canceled by canReadMessage: false' if @debug - return - - rid = Session.get 'openedRoom' - if not rid? - console.log 'readMessage -> readNow canceled, no rid informed' if @debug - return - - if force is true - console.log 'readMessage -> readNow via force rid:', rid if @debug - return Meteor.call 'readMessages', rid, -> - RoomHistoryManager.getRoom(rid).unreadNotLoaded.set 0 - self.refreshUnreadMark() - self.fireRead rid - - subscription = ChatSubscription.findOne rid: rid - if not subscription? - console.log 'readMessage -> readNow canceled, no subscription found for rid:', rid if @debug - return - - if subscription.alert is false and subscription.unread is 0 - console.log 'readMessage -> readNow canceled, alert', subscription.alert, 'and unread', subscription.unread if @debug - return - - room = RoomManager.getOpenedRoomByRid rid - if not room? - console.log 'readMessage -> readNow canceled, no room found for typeName:', subscription.t + subscription.name if @debug - return - - # Only read messages if user saw the first unread message - unreadMark = $('.message.first-unread') - if unreadMark.length > 0 - position = unreadMark.position() - visible = position?.top >= 0 - if not visible and room.unreadSince.get()? - console.log 'readMessage -> readNow canceled, unread mark visible:', visible, 'unread since exists', room.unreadSince.get()? if @debug - return - - console.log 'readMessage -> readNow rid:', rid if @debug - Meteor.call 'readMessages', rid, -> - RoomHistoryManager.getRoom(rid).unreadNotLoaded.set 0 - self.refreshUnreadMark() - self.fireRead rid - - read: _.debounce (force) -> - @readNow(force) - , 1000 - - disable: -> - @canReadMessage = false - - enable: -> - @canReadMessage = document.hasFocus() - - isEnable: -> - return @canReadMessage is true - - onRead: (cb) -> - @callbacks.push cb - - fireRead: (rid) -> - for cb in @callbacks - cb(rid) - - refreshUnreadMark: (rid, force) -> - self = @ - - rid ?= Session.get 'openedRoom' - if not rid? - return - - subscription = ChatSubscription.findOne rid: rid, {reactive: false} - if not subscription? - return - - room = RoomManager.openedRooms[subscription.t + subscription.name] - if not room? - return - - $roomDom = $(room.dom) - $roomDom.find('.message.first-unread').addClass('first-unread-opaque') - - if not subscription.alert and subscription.unread is 0 - room.unreadSince.set undefined - return - - if not force? and subscription.rid is Session.get('openedRoom') and document.hasFocus() - return - - $roomDom.find('.message.first-unread').removeClass('first-unread').removeClass('first-unread-opaque') - - lastReadRecord = ChatMessage.findOne - rid: subscription.rid - ts: - $lt: subscription.ls - # 'u._id': - # $ne: Meteor.userId() - , - sort: - ts: -1 - - if not lastReadRecord? and RoomHistoryManager.getRoom(room.rid).unreadNotLoaded.get() is 0 - lastReadRecord = - ts: new Date(0) - - if lastReadRecord? or RoomHistoryManager.getRoom(room.rid).unreadNotLoaded.get() > 0 - room.unreadSince.set subscription.ls - else - room.unreadSince.set undefined - - if lastReadRecord? - firstUnreadRecord = ChatMessage.findOne - rid: subscription.rid - ts: - $gt: lastReadRecord.ts - 'u._id': - $ne: Meteor.userId() - , - sort: - ts: 1 - - if firstUnreadRecord? - room.unreadFirstId = firstUnreadRecord._id - $roomDom.find('.message#'+firstUnreadRecord._id).addClass('first-unread') - - -Meteor.startup -> - $(window).on 'blur', -> - readMessage.disable() - - $(window).on 'focus', -> - readMessage.enable() - readMessage.read() - - $(window).on 'click', (e) -> - readMessage.enable() - readMessage.read() - - $(window).on 'touchend', (e) -> - readMessage.enable() - readMessage.read() - - $(window).on 'keyup', (e) -> - key = e.which - - if key is 27 - readMessage.enable() - readMessage.readNow(true) - $('.message.first-unread').removeClass('first-unread') diff --git a/packages/rocketchat-ui/client/lib/recorderjs/audioRecorder.coffee b/packages/rocketchat-ui/client/lib/recorderjs/audioRecorder.coffee deleted file mode 100644 index e51dbeff7a2..00000000000 --- a/packages/rocketchat-ui/client/lib/recorderjs/audioRecorder.coffee +++ /dev/null @@ -1,41 +0,0 @@ -@AudioRecorder = new class - start: (cb) -> - window.AudioContext = window.AudioContext or window.webkitAudioContext - navigator.getUserMedia = navigator.getUserMedia or navigator.webkitGetUserMedia - window.URL = window.URL or window.webkitURL - - window.audioContext = new AudioContext - - ok = (stream) => - @startUserMedia(stream) - cb?.call(@) - - if not navigator.getUserMedia? - return cb false - - navigator.getUserMedia {audio: true}, ok, (e) -> - console.log('No live audio input: ' + e) - - startUserMedia: (stream) -> - @stream = stream - input = window.audioContext.createMediaStreamSource(stream) - @recorder = new Recorder(input, {workerPath: '/recorderWorker.js'}) - @recorder.record() - - stop: (cb) -> - @recorder.stop() - - if cb? - @getBlob cb - - @stream.getAudioTracks()[0].stop() - - @recorder.clear() - - window.audioContext.close() - delete window.audioContext - delete @recorder - delete @stream - - getBlob: (cb) -> - @recorder.exportWAV cb diff --git a/packages/rocketchat-ui/client/lib/recorderjs/videoRecorder.coffee b/packages/rocketchat-ui/client/lib/recorderjs/videoRecorder.coffee deleted file mode 100644 index 062694df7a0..00000000000 --- a/packages/rocketchat-ui/client/lib/recorderjs/videoRecorder.coffee +++ /dev/null @@ -1,78 +0,0 @@ -@VideoRecorder = new class - started: false - cameraStarted: new ReactiveVar false - recording: new ReactiveVar false - recordingAvailable: new ReactiveVar false - - start: (videoel, cb) -> - navigator.getUserMedia = navigator.getUserMedia or navigator.webkitGetUserMedia or navigator.mozGetUserMedia - window.URL = window.URL or window.webkitURL - - @videoel = videoel - ok = (stream) => - @startUserMedia(stream) - cb?.call(@) - - if not navigator.getUserMedia? - return cb false - - navigator.getUserMedia {audio: true, video: true}, ok, (e) -> - console.log('No live video input: ' + e) - - record: -> - @chunks = [] - if not @stream? - return - @mediaRecorder = new MediaRecorder(@stream) - @mediaRecorder.stream = @stream - @mediaRecorder.mimeType = 'video/webm' - @mediaRecorder.ondataavailable = (blobev) => - @chunks.push(blobev.data) - if not @recordingAvailable.get() - @recordingAvailable.set true - @mediaRecorder.start() - @recording.set true - - startUserMedia: (stream) -> - @stream = stream - @videoel.src = URL.createObjectURL(stream) - @videoel.onloadedmetadata = (e) => - @videoel.play() - - @started = true - @cameraStarted.set true - - stop: (cb) -> - if @started - @stopRecording() - - if @stream? - vtracks = @stream.getVideoTracks() - for vtrack in vtracks - vtrack.stop() - - atracks = @stream.getAudioTracks() - for atrack in atracks - atrack.stop() - - if @videoel? - @videoel.pause - @videoel.src = '' - - @started = false - @cameraStarted.set false - @recordingAvailable.set false - - if cb? and @chunks? - blob = new Blob(@chunks, { 'type' : 'video/webm' }) - cb(blob) - - delete @recorder - delete @stream - delete @videoel - - stopRecording: -> - if @started and @recording and @mediaRecorder? - @mediaRecorder.stop() - @recording.set false - delete @mediaRecorder diff --git a/packages/rocketchat-ui/client/lib/recorderjs/videoRecorder.js b/packages/rocketchat-ui/client/lib/recorderjs/videoRecorder.js index 8ae2be48519..3e2c82f7c9c 100644 --- a/packages/rocketchat-ui/client/lib/recorderjs/videoRecorder.js +++ b/packages/rocketchat-ui/client/lib/recorderjs/videoRecorder.js @@ -16,7 +16,7 @@ this.VideoRecorder = new class { return (cb != null ? cb.call(this) : undefined); }; - if ((navigator.getUserMedia == null)) { + if (navigator.getUserMedia == null) { return cb(false); } @@ -25,7 +25,7 @@ this.VideoRecorder = new class { record() { this.chunks = []; - if ((this.stream == null)) { + if (this.stream == null) { return; } this.mediaRecorder = new MediaRecorder(this.stream); @@ -56,7 +56,7 @@ this.VideoRecorder = new class { if (this.started) { this.stopRecording(); - if (this.stream != null) { + if (this.stream) { const vtracks = this.stream.getVideoTracks(); for (const vtrack of Array.from(vtracks)) { vtrack.stop(); @@ -68,7 +68,7 @@ this.VideoRecorder = new class { } } - if (this.videoel != null) { + if (this.videoel) { this.videoel.pause; this.videoel.src = ''; } @@ -77,7 +77,7 @@ this.VideoRecorder = new class { this.cameraStarted.set(false); this.recordingAvailable.set(false); - if ((cb != null) && (this.chunks != null)) { + if (cb && this.chunks) { const blob = new Blob(this.chunks, { 'type' : 'video/webm' }); cb(blob); } @@ -89,7 +89,7 @@ this.VideoRecorder = new class { } stopRecording() { - if (this.started && this.recording && this.mediaRecorder != null) { + if (this.started && this.recording && this.mediaRecorder) { this.mediaRecorder.stop(); this.recording.set(false); return delete this.mediaRecorder; diff --git a/packages/rocketchat-ui/package.js b/packages/rocketchat-ui/package.js index 83b402db903..f9ad4248d58 100644 --- a/packages/rocketchat-ui/package.js +++ b/packages/rocketchat-ui/package.js @@ -35,7 +35,7 @@ Package.onUse(function(api) { api.addFiles('client/lib/accountBox.js', 'client'); api.addFiles('client/lib/accounts.js', 'client'); api.addFiles('client/lib/avatar.js', 'client'); - api.addFiles('client/lib/chatMessages.coffee', 'client'); + api.addFiles('client/lib/chatMessages.js', 'client'); api.addFiles('client/lib/collections.js', 'client'); api.addFiles('client/lib/customEventPolyfill.js', 'client'); api.addFiles('client/lib/fileUpload.coffee', 'client');