parent
6ac7193519
commit
b3f07535b9
@ -1,254 +0,0 @@ |
||||
import moment from 'moment' |
||||
|
||||
Template.message.helpers |
||||
encodeURI: (text) -> |
||||
return encodeURI(text) |
||||
isBot: -> |
||||
return 'bot' if this.bot? |
||||
roleTags: -> |
||||
if not RocketChat.settings.get('UI_DisplayRoles') or Meteor.user()?.settings?.preferences?.hideRoles |
||||
return [] |
||||
roles = _.union(UserRoles.findOne(this.u?._id)?.roles, RoomRoles.findOne({'u._id': this.u?._id, rid: this.rid })?.roles) |
||||
return RocketChat.models.Roles.find({ _id: { $in: roles }, description: { $exists: 1, $ne: '' } }, { fields: { description: 1 } }) |
||||
isGroupable: -> |
||||
return 'false' if this.groupable is false |
||||
isSequential: -> |
||||
return 'sequential' if this.groupable isnt false |
||||
avatarFromUsername: -> |
||||
if this.avatar? and this.avatar[0] is '@' |
||||
return this.avatar.replace(/^@/, '') |
||||
getEmoji: (emoji) -> |
||||
return renderEmoji emoji |
||||
getName: -> |
||||
if this.alias |
||||
return this.alias |
||||
if RocketChat.settings.get('UI_Use_Real_Name') and this.u?.name |
||||
return this.u.name |
||||
return this.u?.username |
||||
showUsername: -> |
||||
return this.alias or (RocketChat.settings.get('UI_Use_Real_Name') and this.u?.name) |
||||
own: -> |
||||
return 'own' if this.u?._id is Meteor.userId() |
||||
timestamp: -> |
||||
return +this.ts |
||||
chatops: -> |
||||
return 'chatops-message' if this.u?.username is RocketChat.settings.get('Chatops_Username') |
||||
time: -> |
||||
return moment(this.ts).format(RocketChat.settings.get('Message_TimeFormat')) |
||||
date: -> |
||||
return moment(this.ts).format(RocketChat.settings.get('Message_DateFormat')) |
||||
isTemp: -> |
||||
if @temp is true |
||||
return 'temp' |
||||
body: -> |
||||
return Template.instance().body |
||||
system: (returnClass) -> |
||||
if RocketChat.MessageTypes.isSystemMessage(this) |
||||
if returnClass |
||||
return 'color-info-font-color' |
||||
|
||||
return 'system' |
||||
|
||||
showTranslated: -> |
||||
if RocketChat.settings.get('AutoTranslate_Enabled') and this.u?._id isnt Meteor.userId() and !RocketChat.MessageTypes.isSystemMessage(this) |
||||
subscription = RocketChat.models.Subscriptions.findOne({ rid: this.rid, 'u._id': Meteor.userId() }, { fields: { autoTranslate: 1, autoTranslateLanguage: 1 } }); |
||||
language = RocketChat.AutoTranslate.getLanguage(this.rid); |
||||
return this.autoTranslateFetching || (subscription?.autoTranslate isnt this.autoTranslateShowInverse && this.translations && this.translations[language]) # || _.find(this.attachments, (attachment) -> attachment.translations && attachment.translations[language] && attachment.author_name isnt Meteor.user().username ) |
||||
|
||||
edited: -> |
||||
return Template.instance().wasEdited |
||||
|
||||
editTime: -> |
||||
if Template.instance().wasEdited |
||||
return moment(@editedAt).format(RocketChat.settings.get('Message_DateFormat') + ' ' + RocketChat.settings.get('Message_TimeFormat')) |
||||
editedBy: -> |
||||
return "" unless Template.instance().wasEdited |
||||
# try to return the username of the editor, |
||||
# otherwise a special "?" character that will be |
||||
# rendered as a special avatar |
||||
return @editedBy?.username or "?" |
||||
canEdit: -> |
||||
hasPermission = RocketChat.authz.hasAtLeastOnePermission('edit-message', this.rid) |
||||
isEditAllowed = RocketChat.settings.get 'Message_AllowEditing' |
||||
editOwn = this.u?._id is Meteor.userId() |
||||
|
||||
return unless hasPermission or (isEditAllowed and editOwn) |
||||
|
||||
blockEditInMinutes = RocketChat.settings.get 'Message_AllowEditing_BlockEditInMinutes' |
||||
if blockEditInMinutes? and blockEditInMinutes isnt 0 |
||||
msgTs = moment(this.ts) if this.ts? |
||||
currentTsDiff = moment().diff(msgTs, 'minutes') if msgTs? |
||||
return currentTsDiff < blockEditInMinutes |
||||
else |
||||
return true |
||||
|
||||
canDelete: -> |
||||
hasPermission = RocketChat.authz.hasAtLeastOnePermission('delete-message', this.rid ) |
||||
isDeleteAllowed = RocketChat.settings.get('Message_AllowDeleting') |
||||
deleteOwn = this.u?._id is Meteor.userId() |
||||
|
||||
return unless hasPermission or (isDeleteAllowed and deleteOwn) |
||||
|
||||
blockDeleteInMinutes = RocketChat.settings.get 'Message_AllowDeleting_BlockDeleteInMinutes' |
||||
if blockDeleteInMinutes? and blockDeleteInMinutes isnt 0 |
||||
msgTs = moment(this.ts) if this.ts? |
||||
currentTsDiff = moment().diff(msgTs, 'minutes') if msgTs? |
||||
return currentTsDiff < blockDeleteInMinutes |
||||
else |
||||
return true |
||||
|
||||
showEditedStatus: -> |
||||
return RocketChat.settings.get 'Message_ShowEditedStatus' |
||||
label: -> |
||||
if @i18nLabel |
||||
return t(@i18nLabel) |
||||
else if @label |
||||
return @label |
||||
|
||||
hasOembed: -> |
||||
return false unless this.urls?.length > 0 and Template.oembedBaseWidget? and RocketChat.settings.get 'API_Embed' |
||||
|
||||
return false unless this.u?.username not in RocketChat.settings.get('API_EmbedDisabledFor')?.split(',').map (username) -> username.trim() |
||||
|
||||
return true |
||||
|
||||
reactions: -> |
||||
msgReactions = [] |
||||
userUsername = Meteor.user()?.username |
||||
|
||||
for emoji, reaction of @reactions |
||||
total = reaction.usernames.length |
||||
usernames = '@' + reaction.usernames.slice(0, 15).join(', @') |
||||
|
||||
usernames = usernames.replace('@'+userUsername, t('You').toLowerCase()) |
||||
|
||||
if total > 15 |
||||
usernames = usernames + ' ' + t('And_more', { length: total - 15 }).toLowerCase() |
||||
else |
||||
usernames = usernames.replace(/,([^,]+)$/, ' '+t('and')+'$1') |
||||
|
||||
if usernames[0] isnt '@' |
||||
usernames = usernames[0].toUpperCase() + usernames.substr(1) |
||||
|
||||
msgReactions.push |
||||
emoji: emoji |
||||
count: reaction.usernames.length |
||||
usernames: usernames |
||||
reaction: ' ' + t('Reacted_with').toLowerCase() + ' ' + emoji |
||||
userReacted: reaction.usernames.indexOf(userUsername) > -1 |
||||
|
||||
return msgReactions |
||||
|
||||
markUserReaction: (reaction) -> |
||||
if reaction.userReacted |
||||
return { |
||||
class: 'selected' |
||||
} |
||||
|
||||
hideReactions: -> |
||||
return 'hidden' if _.isEmpty(@reactions) |
||||
|
||||
actionLinks: -> |
||||
# remove 'method_id' and 'params' properties |
||||
return _.map(@actionLinks, (actionLink, key) -> _.extend({ id: key }, _.omit(actionLink, 'method_id', 'params'))) |
||||
|
||||
hideActionLinks: -> |
||||
return 'hidden' if _.isEmpty(@actionLinks) |
||||
|
||||
injectIndex: (data, index) -> |
||||
data.index = index |
||||
return |
||||
|
||||
hideCog: -> |
||||
subscription = RocketChat.models.Subscriptions.findOne({ rid: this.rid }); |
||||
return 'hidden' if not subscription? |
||||
|
||||
hideUsernames: -> |
||||
prefs = Meteor.user()?.settings?.preferences |
||||
return if prefs?.hideUsernames |
||||
|
||||
Template.message.onCreated -> |
||||
msg = Template.currentData() |
||||
|
||||
@wasEdited = msg.editedAt? and not RocketChat.MessageTypes.isSystemMessage(msg) |
||||
|
||||
@body = do -> |
||||
isSystemMessage = RocketChat.MessageTypes.isSystemMessage(msg) |
||||
messageType = RocketChat.MessageTypes.getType(msg) |
||||
if messageType?.render? |
||||
msg = messageType.render(msg) |
||||
else if messageType?.template? |
||||
# render template |
||||
else if messageType?.message? |
||||
if messageType.data?(msg)? |
||||
msg = TAPi18n.__(messageType.message, messageType.data(msg)) |
||||
else |
||||
msg = TAPi18n.__(messageType.message) |
||||
else |
||||
if msg.u?.username is RocketChat.settings.get('Chatops_Username') |
||||
msg.html = msg.msg |
||||
msg = RocketChat.callbacks.run 'renderMentions', msg |
||||
# console.log JSON.stringify message |
||||
msg = msg.html |
||||
else |
||||
msg = renderMessageBody msg |
||||
|
||||
if isSystemMessage |
||||
msg.html = RocketChat.Markdown.parse msg.html |
||||
|
||||
return msg |
||||
|
||||
Template.message.onViewRendered = (context) -> |
||||
view = this |
||||
this._domrange.onAttached (domRange) -> |
||||
currentNode = domRange.lastNode() |
||||
currentDataset = currentNode.dataset |
||||
previousNode = currentNode.previousElementSibling |
||||
nextNode = currentNode.nextElementSibling |
||||
$currentNode = $(currentNode) |
||||
$nextNode = $(nextNode) |
||||
|
||||
unless previousNode? |
||||
$currentNode.addClass('new-day').removeClass('sequential') |
||||
|
||||
else if previousNode?.dataset? |
||||
previousDataset = previousNode.dataset |
||||
previousMessageDate = new Date(parseInt(previousDataset.timestamp)) |
||||
currentMessageDate = new Date(parseInt(currentDataset.timestamp)) |
||||
|
||||
if previousMessageDate.toDateString() isnt currentMessageDate.toDateString() |
||||
$currentNode.addClass('new-day').removeClass('sequential') |
||||
else |
||||
$currentNode.removeClass('new-day') |
||||
|
||||
if previousDataset.groupable is 'false' or currentDataset.groupable is 'false' |
||||
$currentNode.removeClass('sequential') |
||||
else |
||||
if previousDataset.username isnt currentDataset.username or parseInt(currentDataset.timestamp) - parseInt(previousDataset.timestamp) > RocketChat.settings.get('Message_GroupingPeriod') * 1000 |
||||
$currentNode.removeClass('sequential') |
||||
else if not $currentNode.hasClass 'new-day' |
||||
$currentNode.addClass('sequential') |
||||
|
||||
if nextNode?.dataset? |
||||
nextDataset = nextNode.dataset |
||||
|
||||
if nextDataset.date isnt currentDataset.date |
||||
$nextNode.addClass('new-day').removeClass('sequential') |
||||
else |
||||
$nextNode.removeClass('new-day') |
||||
|
||||
if nextDataset.groupable isnt 'false' |
||||
if nextDataset.username isnt currentDataset.username or parseInt(nextDataset.timestamp) - parseInt(currentDataset.timestamp) > RocketChat.settings.get('Message_GroupingPeriod') * 1000 |
||||
$nextNode.removeClass('sequential') |
||||
else if not $nextNode.hasClass 'new-day' |
||||
$nextNode.addClass('sequential') |
||||
|
||||
if not nextNode? |
||||
templateInstance = if $('#chat-window-' + context.rid)[0] then Blaze.getView($('#chat-window-' + context.rid)[0])?.templateInstance() else null |
||||
|
||||
if currentNode.classList.contains('own') is true |
||||
templateInstance?.atBottom = true |
||||
else |
||||
if templateInstance?.firstNode && templateInstance?.atBottom is false |
||||
newMessage = templateInstance?.find(".new-message") |
||||
newMessage?.className = "new-message background-primary-action-color color-content-background-color " |
@ -1,391 +0,0 @@ |
||||
import toastr from 'toastr' |
||||
import mime from 'mime-type/with-db' |
||||
import moment from 'moment' |
||||
import {VRecDialog} from 'meteor/rocketchat:ui-vrecord' |
||||
|
||||
katexSyntax = -> |
||||
if RocketChat.katex.katex_enabled() |
||||
return "$$KaTeX$$" if RocketChat.katex.dollar_syntax_enabled() |
||||
return "\\[KaTeX\\]" if RocketChat.katex.parenthesis_syntax_enabled() |
||||
|
||||
return false |
||||
|
||||
Template.messageBox.helpers |
||||
roomName: -> |
||||
roomData = Session.get('roomData' + this._id) |
||||
return '' unless roomData |
||||
|
||||
if roomData.t is 'd' |
||||
return ChatSubscription.findOne({ rid: this._id }, { fields: { name: 1 } })?.name |
||||
else |
||||
return roomData.name |
||||
showMarkdown: -> |
||||
return RocketChat.Markdown |
||||
showMarkdownCode: -> |
||||
return RocketChat.MarkdownCode |
||||
showKatex: -> |
||||
return RocketChat.katex |
||||
katexSyntax: -> |
||||
return katexSyntax() |
||||
showFormattingTips: -> |
||||
return RocketChat.settings.get('Message_ShowFormattingTips') and (RocketChat.Markdown or RocketChat.MarkdownCode or katexSyntax()) |
||||
canJoin: -> |
||||
return Meteor.userId()? and RocketChat.roomTypes.verifyShowJoinLink @_id |
||||
joinCodeRequired: -> |
||||
return Session.get('roomData' + this._id)?.joinCodeRequired |
||||
subscribed: -> |
||||
return RocketChat.roomTypes.verifyCanSendMessage @_id |
||||
allowedToSend: -> |
||||
if RocketChat.roomTypes.readOnly @_id, Meteor.user() |
||||
return false |
||||
|
||||
if RocketChat.roomTypes.archived @_id |
||||
return false |
||||
|
||||
roomData = Session.get('roomData' + this._id) |
||||
if roomData?.t is 'd' |
||||
subscription = ChatSubscription.findOne({ rid: this._id }, { fields: { archived: 1, blocked: 1, blocker: 1 } }) |
||||
if subscription and (subscription.archived or subscription.blocked or subscription.blocker) |
||||
return false |
||||
|
||||
return true |
||||
isBlockedOrBlocker: -> |
||||
roomData = Session.get('roomData' + this._id) |
||||
if roomData?.t is 'd' |
||||
subscription = ChatSubscription.findOne({ rid: this._id }, { fields: { blocked: 1, blocker: 1 } }) |
||||
if subscription and (subscription.blocked or subscription.blocker) |
||||
return true |
||||
|
||||
getPopupConfig: -> |
||||
template = Template.instance() |
||||
return { |
||||
getInput: -> |
||||
return template.find('.input-message') |
||||
} |
||||
usersTyping: -> |
||||
users = MsgTyping.get @_id |
||||
if users.length is 0 |
||||
return |
||||
if users.length is 1 |
||||
return { |
||||
multi: false |
||||
selfTyping: MsgTyping.selfTyping.get() |
||||
users: users[0] |
||||
} |
||||
# usernames = _.map messages, (message) -> return message.u.username |
||||
last = users.pop() |
||||
if users.length > 4 |
||||
last = t('others') |
||||
# else |
||||
usernames = users.join(', ') |
||||
usernames = [usernames, last] |
||||
return { |
||||
multi: true |
||||
selfTyping: MsgTyping.selfTyping.get() |
||||
users: usernames.join " #{t 'and'} " |
||||
} |
||||
|
||||
groupAttachHidden: -> |
||||
return 'hidden' if RocketChat.settings.get('Message_Attachments_GroupAttach') |
||||
|
||||
fileUploadEnabled: -> |
||||
return RocketChat.settings.get('FileUpload_Enabled') |
||||
|
||||
fileUploadAllowedMediaTypes: -> |
||||
return RocketChat.settings.get('FileUpload_MediaTypeWhiteList') |
||||
|
||||
showFileUpload: -> |
||||
if (RocketChat.settings.get('FileUpload_Enabled')) |
||||
roomData = Session.get('roomData' + this._id) |
||||
if roomData?.t is 'd' |
||||
return RocketChat.settings.get('FileUpload_Enabled_Direct') |
||||
else |
||||
return true |
||||
else |
||||
return RocketChat.settings.get('FileUpload_Enabled') |
||||
|
||||
|
||||
showMic: -> |
||||
return Template.instance().showMicButton.get() |
||||
|
||||
showVRec: -> |
||||
return Template.instance().showVideoRec.get() |
||||
|
||||
showSend: -> |
||||
if not Template.instance().isMessageFieldEmpty.get() |
||||
return 'show-send' |
||||
|
||||
showLocation: -> |
||||
return RocketChat.Geolocation.get() isnt false |
||||
|
||||
notSubscribedTpl: -> |
||||
return RocketChat.roomTypes.getNotSubscribedTpl @_id |
||||
|
||||
showSandstorm: -> |
||||
return Meteor.settings.public.sandstorm && !Meteor.isCordova |
||||
|
||||
anonymousRead: -> |
||||
return not Meteor.userId()? and RocketChat.settings.get('Accounts_AllowAnonymousRead') is true |
||||
|
||||
anonymousWrite: -> |
||||
return not Meteor.userId()? and RocketChat.settings.get('Accounts_AllowAnonymousRead') is true and RocketChat.settings.get('Accounts_AllowAnonymousWrite') is true |
||||
|
||||
firefoxPasteUpload = (fn) -> |
||||
user = navigator.userAgent.match(/Firefox\/(\d+)\.\d/) |
||||
if !user or user[1] > 49 |
||||
return fn |
||||
return (event, instance) -> |
||||
if (event.originalEvent.ctrlKey or event.originalEvent.metaKey) and (event.keyCode == 86) |
||||
textarea = instance.find("textarea") |
||||
selectionStart = textarea.selectionStart |
||||
selectionEnd = textarea.selectionEnd |
||||
contentEditableDiv = instance.find('#msg_contenteditable') |
||||
contentEditableDiv.focus() |
||||
Meteor.setTimeout -> |
||||
pastedImg = contentEditableDiv.querySelector 'img' |
||||
textareaContent = textarea.value |
||||
startContent = textareaContent.substring(0, selectionStart) |
||||
endContent = textareaContent.substring(selectionEnd) |
||||
restoreSelection = (pastedText) -> |
||||
textarea.value = startContent + pastedText + endContent |
||||
textarea.selectionStart = selectionStart + pastedText.length |
||||
textarea.selectionEnd = textarea.selectionStart |
||||
contentEditableDiv.innerHTML = '' if pastedImg |
||||
textarea.focus |
||||
return if (!pastedImg || contentEditableDiv.innerHTML.length > 0) |
||||
[].slice.call(contentEditableDiv.querySelectorAll("br")).forEach (el) -> |
||||
contentEditableDiv.replaceChild(new Text("\n") , el) |
||||
restoreSelection(contentEditableDiv.innerText) |
||||
imageSrc = pastedImg.getAttribute("src") |
||||
if imageSrc.match(/^data:image/) |
||||
fetch(imageSrc) |
||||
.then((img)-> |
||||
return img.blob()) |
||||
.then (blob)-> |
||||
fileUpload [{ |
||||
file: blob |
||||
name: 'Clipboard' |
||||
}] |
||||
, 150 |
||||
fn?.apply @, arguments |
||||
|
||||
|
||||
Template.messageBox.events |
||||
'click .join': (event) -> |
||||
event.stopPropagation() |
||||
event.preventDefault() |
||||
Meteor.call 'joinRoom', @_id, Template.instance().$('[name=joinCode]').val(), (err) => |
||||
if err? |
||||
toastr.error t(err.reason) |
||||
|
||||
if RocketChat.authz.hasAllPermission('preview-c-room') is false and RoomHistoryManager.getRoom(@_id).loaded is 0 |
||||
RoomManager.getOpenedRoomByRid(@_id).streamActive = false |
||||
RoomManager.getOpenedRoomByRid(@_id).ready = false |
||||
RoomHistoryManager.getRoom(@_id).loaded = undefined |
||||
RoomManager.computation.invalidate() |
||||
|
||||
'click .register': (event) -> |
||||
event.stopPropagation() |
||||
event.preventDefault() |
||||
Session.set('forceLogin', true) |
||||
|
||||
'click .register-anonymous': (event) -> |
||||
event.stopPropagation() |
||||
event.preventDefault() |
||||
|
||||
Meteor.call 'registerUser', {}, (error, loginData) -> |
||||
if loginData && loginData.token |
||||
Meteor.loginWithToken loginData.token |
||||
|
||||
|
||||
'focus .input-message': (event, instance) -> |
||||
KonchatNotification.removeRoomNotification @_id |
||||
chatMessages[@_id].input = instance.find('.input-message') |
||||
|
||||
'click .send-button': (event, instance) -> |
||||
input = instance.find('.input-message') |
||||
chatMessages[@_id].send(@_id, input, => |
||||
# fixes https://github.com/RocketChat/Rocket.Chat/issues/3037 |
||||
# at this point, the input is cleared and ready for autogrow |
||||
input.updateAutogrow() |
||||
instance.isMessageFieldEmpty.set(chatMessages[@_id].isEmpty()) |
||||
) |
||||
input.focus() |
||||
|
||||
'keyup .input-message': (event, instance) -> |
||||
chatMessages[@_id].keyup(@_id, event, instance) |
||||
instance.isMessageFieldEmpty.set(chatMessages[@_id].isEmpty()) |
||||
|
||||
'paste .input-message': (e, instance) -> |
||||
Meteor.setTimeout -> |
||||
input = instance.find('.input-message') |
||||
input.updateAutogrow?() |
||||
, 50 |
||||
|
||||
if not e.originalEvent.clipboardData? |
||||
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 - ' + moment().format(RocketChat.settings.get('Message_TimeAndDateFormat')) |
||||
|
||||
if files.length |
||||
fileUpload files |
||||
else |
||||
instance.isMessageFieldEmpty.set(false) |
||||
|
||||
'keydown .input-message': firefoxPasteUpload((event, instance) -> |
||||
chatMessages[@_id].keydown(@_id, event, Template.instance())) |
||||
|
||||
'input .input-message': (event) -> |
||||
chatMessages[@_id].valueChanged(@_id, event, Template.instance()) |
||||
|
||||
'propertychange .input-message': (event) -> |
||||
if event.originalEvent.propertyName is 'value' |
||||
chatMessages[@_id].valueChanged(@_id, event, Template.instance()) |
||||
|
||||
"click .editing-commands-cancel > button": (e) -> |
||||
chatMessages[@_id].clearEditing() |
||||
|
||||
"click .editing-commands-save > button": (e) -> |
||||
chatMessages[@_id].send(@_id, chatMessages[@_id].input) |
||||
|
||||
'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 |
||||
# `file.type = mime.lookup(file.name)` does not work. |
||||
Object.defineProperty(file, 'type', { value: mime.lookup(file.name) }) |
||||
filesToUpload.push |
||||
file: file |
||||
name: file.name |
||||
|
||||
fileUpload filesToUpload |
||||
|
||||
"click .message-buttons.share": (e, t) -> |
||||
t.$('.share-items').toggleClass('hidden') |
||||
t.$('.message-buttons.share').toggleClass('active') |
||||
|
||||
'click .message-form .message-buttons.location': (event, instance) -> |
||||
roomId = @_id |
||||
|
||||
position = RocketChat.Geolocation.get() |
||||
|
||||
latitude = position.coords.latitude |
||||
longitude = position.coords.longitude |
||||
|
||||
text = """ |
||||
<div class="location-preview"> |
||||
<img style="height: 250px; width: 250px;" src="https://maps.googleapis.com/maps/api/staticmap?zoom=14&size=250x250&markers=color:gray%7Clabel:%7C#{latitude},#{longitude}&key=#{RocketChat.settings.get('MapView_GMapsAPIKey')}" /> |
||||
</div> |
||||
""" |
||||
|
||||
swal |
||||
title: t('Share_Location_Title') |
||||
text: text |
||||
showCancelButton: true |
||||
closeOnConfirm: true |
||||
closeOnCancel: true |
||||
html: true |
||||
, (isConfirm) -> |
||||
if isConfirm isnt true |
||||
return |
||||
|
||||
Meteor.call "sendMessage", |
||||
_id: Random.id() |
||||
rid: roomId |
||||
msg: "" |
||||
location: |
||||
type: 'Point' |
||||
coordinates: [ longitude, latitude ] |
||||
|
||||
|
||||
'click .message-form .mic': (e, t) -> |
||||
AudioRecorder.start -> |
||||
t.$('.stop-mic').removeClass('hidden') |
||||
t.$('.mic').addClass('hidden') |
||||
|
||||
'click .message-form .video-button': (e, t) -> |
||||
if VRecDialog.opened |
||||
VRecDialog.close() |
||||
else |
||||
VRecDialog.open(e.currentTarget) |
||||
|
||||
'click .message-form .stop-mic': (e, t) -> |
||||
AudioRecorder.stop (blob) -> |
||||
fileUpload [{ |
||||
file: blob |
||||
type: 'audio' |
||||
name: TAPi18n.__('Audio record') + '.wav' |
||||
}] |
||||
|
||||
t.$('.stop-mic').addClass('hidden') |
||||
t.$('.mic').removeClass('hidden') |
||||
|
||||
'click .sandstorm-offer': (e, t) -> |
||||
roomId = @_id |
||||
RocketChat.Sandstorm.request "uiView", (err, data) => |
||||
if err or !data.token |
||||
console.error err |
||||
return |
||||
Meteor.call "sandstormClaimRequest", data.token, data.descriptor, (err, viewInfo) => |
||||
if err |
||||
console.error err |
||||
return |
||||
|
||||
Meteor.call "sendMessage", { |
||||
_id: Random.id() |
||||
rid: roomId |
||||
msg: "" |
||||
urls: [{ url: "grain://sandstorm", sandstormViewInfo: viewInfo }] |
||||
} |
||||
|
||||
Template.messageBox.onCreated -> |
||||
@isMessageFieldEmpty = new ReactiveVar true |
||||
@showMicButton = new ReactiveVar false |
||||
@showVideoRec = new ReactiveVar false |
||||
|
||||
@autorun => |
||||
videoRegex = /video\/webm|video\/\*/i |
||||
videoEnabled = !RocketChat.settings.get("FileUpload_MediaTypeWhiteList") || RocketChat.settings.get("FileUpload_MediaTypeWhiteList").match(videoRegex) |
||||
if RocketChat.settings.get('Message_VideoRecorderEnabled') and (navigator.getUserMedia? or navigator.webkitGetUserMedia?) and videoEnabled and RocketChat.settings.get('FileUpload_Enabled') |
||||
@showVideoRec.set true |
||||
else |
||||
@showVideoRec.set false |
||||
|
||||
wavRegex = /audio\/wav|audio\/\*/i |
||||
wavEnabled = !RocketChat.settings.get("FileUpload_MediaTypeWhiteList") || RocketChat.settings.get("FileUpload_MediaTypeWhiteList").match(wavRegex) |
||||
if RocketChat.settings.get('Message_AudioRecorderEnabled') and (navigator.getUserMedia? or navigator.webkitGetUserMedia?) and wavEnabled and RocketChat.settings.get('FileUpload_Enabled') |
||||
@showMicButton.set true |
||||
else |
||||
@showMicButton.set false |
||||
|
||||
|
||||
Meteor.startup -> |
||||
RocketChat.Geolocation = new ReactiveVar false |
||||
|
||||
Tracker.autorun -> |
||||
if RocketChat.settings.get('MapView_Enabled') is true and RocketChat.settings.get('MapView_GMapsAPIKey')?.length and navigator.geolocation?.getCurrentPosition? |
||||
success = (position) => |
||||
RocketChat.Geolocation.set position |
||||
|
||||
error = (error) => |
||||
console.log 'Error getting your geolocation', error |
||||
RocketChat.Geolocation.set false |
||||
|
||||
options = |
||||
enableHighAccuracy: true |
||||
maximumAge: 0 |
||||
timeout: 10000 |
||||
|
||||
navigator.geolocation.watchPosition success, error |
||||
else |
||||
RocketChat.Geolocation.set false |
@ -1,282 +0,0 @@ |
||||
# This is not supposed to be a complete list |
||||
# it is just to improve readability in this file |
||||
keys = { |
||||
TAB: 9 |
||||
ENTER: 13 |
||||
ESC: 27 |
||||
ARROW_LEFT: 37 |
||||
ARROW_UP: 38 |
||||
ARROW_RIGHT: 39 |
||||
ARROW_DOWN: 40 |
||||
} |
||||
|
||||
getCursorPosition = (input) -> |
||||
if not input? then return |
||||
if input.selectionStart? |
||||
return input.selectionStart |
||||
else if document.selection? |
||||
input.focus() |
||||
sel = document.selection.createRange() |
||||
selLen = document.selection.createRange().text.length |
||||
sel.moveStart('character', - input.value.length) |
||||
return sel.text.length - selLen |
||||
|
||||
setCursorPosition = (input, caretPos) -> |
||||
if not input? then return |
||||
if input.selectionStart? |
||||
input.focus() |
||||
return input.setSelectionRange(caretPos, caretPos) |
||||
else if document.selection? |
||||
range = input.createTextRange() |
||||
range.move('character', caretPos) |
||||
range.select() |
||||
|
||||
val = (v, d) -> |
||||
return if v? then v else d |
||||
|
||||
Template.messagePopup.onCreated -> |
||||
template = this |
||||
|
||||
template.textFilter = new ReactiveVar '' |
||||
|
||||
template.textFilterDelay = val(template.data.textFilterDelay, 0) |
||||
|
||||
template.open = val(template.data.open, new ReactiveVar(false)) |
||||
|
||||
template.hasData = new ReactiveVar false |
||||
|
||||
template.value = new ReactiveVar |
||||
|
||||
template.trigger = val(template.data.trigger, '') |
||||
|
||||
template.triggerAnywhere = val(template.data.triggerAnywhere, true) |
||||
|
||||
template.closeOnEsc = val(template.data.closeOnEsc, true) |
||||
|
||||
template.blurOnSelectItem = val(template.data.blurOnSelectItem, false) |
||||
|
||||
template.prefix = val(template.data.prefix, template.trigger) |
||||
|
||||
template.suffix = val(template.data.suffix, '') |
||||
|
||||
if template.triggerAnywhere is true |
||||
template.matchSelectorRegex = val(template.data.matchSelectorRegex, new RegExp "(?:^| )#{template.trigger}[^\\s]*$") |
||||
else |
||||
template.matchSelectorRegex = val(template.data.matchSelectorRegex, new RegExp "(?:^)#{template.trigger}[^\\s]*$") |
||||
|
||||
template.selectorRegex = val(template.data.selectorRegex, new RegExp "#{template.trigger}([^\\s]*)$") |
||||
|
||||
template.replaceRegex = val(template.data.replaceRegex, new RegExp "#{template.trigger}[^\\s]*$") |
||||
|
||||
template.getValue = val template.data.getValue, (_id) -> return _id |
||||
|
||||
template.up = => |
||||
current = template.find('.popup-item.selected') |
||||
previous = $(current).prev('.popup-item')[0] or template.find('.popup-item:last-child') |
||||
if previous? |
||||
current.className = current.className.replace /\sselected/, '' |
||||
previous.className += ' selected' |
||||
template.value.set previous.getAttribute('data-id') |
||||
|
||||
template.down = => |
||||
current = template.find('.popup-item.selected') |
||||
next = $(current).next('.popup-item')[0] or template.find('.popup-item') |
||||
if next?.classList.contains('popup-item') |
||||
current.className = current.className.replace /\sselected/, '' |
||||
next.className += ' selected' |
||||
template.value.set next.getAttribute('data-id') |
||||
|
||||
template.verifySelection = => |
||||
current = template.find('.popup-item.selected') |
||||
if not current? |
||||
first = template.find('.popup-item') |
||||
if first? |
||||
first.className += ' selected' |
||||
template.value.set first.getAttribute('data-id') |
||||
else |
||||
template.value.set undefined |
||||
|
||||
template.onInputKeydown = (event) => |
||||
if template.open.curValue isnt true or template.hasData.curValue isnt true |
||||
return |
||||
|
||||
if event.which in [keys.ENTER, keys.TAB] |
||||
if template.blurOnSelectItem is true |
||||
template.input.blur() |
||||
else |
||||
template.open.set false |
||||
|
||||
template.enterValue() |
||||
|
||||
if template.data.cleanOnEnter |
||||
template.input.value = '' |
||||
|
||||
event.preventDefault() |
||||
event.stopPropagation() |
||||
return |
||||
|
||||
if event.which is keys.ARROW_UP |
||||
template.up() |
||||
|
||||
event.preventDefault() |
||||
event.stopPropagation() |
||||
return |
||||
|
||||
if event.which is keys.ARROW_DOWN |
||||
template.down() |
||||
|
||||
event.preventDefault() |
||||
event.stopPropagation() |
||||
return |
||||
|
||||
template.setTextFilter = _.debounce (value) -> |
||||
template.textFilter.set(value) |
||||
, template.textFilterDelay |
||||
|
||||
template.onInputKeyup = (event) => |
||||
if template.closeOnEsc is true and template.open.curValue is true and event.which is keys.ESC |
||||
template.open.set false |
||||
event.preventDefault() |
||||
event.stopPropagation() |
||||
return |
||||
|
||||
value = template.input.value |
||||
value = value.substr 0, getCursorPosition(template.input) |
||||
|
||||
if template.matchSelectorRegex.test value |
||||
template.setTextFilter value.match(template.selectorRegex)[1] |
||||
template.open.set true |
||||
else |
||||
template.open.set false |
||||
|
||||
if template.open.curValue isnt true |
||||
return |
||||
|
||||
if event.which not in [keys.ARROW_UP, keys.ARROW_DOWN] |
||||
Meteor.defer => |
||||
template.verifySelection() |
||||
|
||||
template.onFocus = (event) => |
||||
template.clickingItem = false; |
||||
|
||||
if template.open.curValue is true |
||||
return |
||||
|
||||
value = template.input.value |
||||
value = value.substr 0, getCursorPosition(template.input) |
||||
|
||||
if template.matchSelectorRegex.test value |
||||
template.setTextFilter value.match(template.selectorRegex)[1] |
||||
template.open.set true |
||||
Meteor.defer => |
||||
template.verifySelection() |
||||
else |
||||
template.open.set false |
||||
|
||||
template.onBlur = (event) => |
||||
if template.open.curValue is false |
||||
return |
||||
|
||||
if template.clickingItem is true |
||||
return |
||||
|
||||
template.open.set false |
||||
|
||||
template.enterValue = -> |
||||
if not template.value.curValue? then return |
||||
|
||||
value = template.input.value |
||||
caret = getCursorPosition(template.input) |
||||
firstPartValue = value.substr 0, caret |
||||
lastPartValue = value.substr caret |
||||
getValue = this.getValue(template.value.curValue, template.data.collection, template.records.get(), firstPartValue) |
||||
|
||||
if not getValue |
||||
return |
||||
|
||||
firstPartValue = firstPartValue.replace(template.selectorRegex, template.prefix + getValue + template.suffix) |
||||
|
||||
template.input.value = firstPartValue + lastPartValue |
||||
|
||||
setCursorPosition template.input, firstPartValue.length |
||||
|
||||
template.records = new ReactiveVar [] |
||||
Tracker.autorun -> |
||||
if template.data.collection.findOne? |
||||
template.data.collection.find().count() |
||||
|
||||
filter = template.textFilter.get() |
||||
if filter? |
||||
filterCallback = (result) => |
||||
template.hasData.set result?.length > 0 |
||||
template.records.set result |
||||
|
||||
Meteor.defer => |
||||
template.verifySelection() |
||||
|
||||
result = template.data.getFilter(template.data.collection, filter, filterCallback) |
||||
if result? |
||||
filterCallback result |
||||
|
||||
|
||||
Template.messagePopup.onRendered -> |
||||
if this.data.getInput? |
||||
this.input = this.data.getInput?() |
||||
else if this.data.input |
||||
this.input = this.parentTemplate().find(this.data.input) |
||||
|
||||
if not this.input? |
||||
console.error 'Input not found for popup' |
||||
|
||||
$(this.input).on 'keyup', this.onInputKeyup.bind this |
||||
$(this.input).on 'keydown', this.onInputKeydown.bind this |
||||
$(this.input).on 'focus', this.onFocus.bind this |
||||
$(this.input).on 'blur', this.onBlur.bind this |
||||
|
||||
|
||||
Template.messagePopup.onDestroyed -> |
||||
$(this.input).off 'keyup', this.onInputKeyup |
||||
$(this.input).off 'keydown', this.onInputKeydown |
||||
$(this.input).off 'focus', this.onFocus |
||||
$(this.input).off 'blur', this.onBlur |
||||
|
||||
|
||||
Template.messagePopup.events |
||||
'mouseenter .popup-item': (e) -> |
||||
if e.currentTarget.className.indexOf('selected') > -1 |
||||
return |
||||
|
||||
template = Template.instance() |
||||
|
||||
current = template.find('.popup-item.selected') |
||||
if current? |
||||
current.className = current.className.replace /\sselected/, '' |
||||
e.currentTarget.className += ' selected' |
||||
template.value.set this._id |
||||
|
||||
'mousedown .popup-item, touchstart .popup-item': (e) -> |
||||
template = Template.instance() |
||||
template.clickingItem = true; |
||||
|
||||
'mouseup .popup-item, touchend .popup-item': (e) -> |
||||
template = Template.instance() |
||||
|
||||
template.clickingItem = false; |
||||
|
||||
template.value.set this._id |
||||
|
||||
template.enterValue() |
||||
|
||||
template.open.set false |
||||
|
||||
toolbarSearch.clear(); |
||||
|
||||
|
||||
Template.messagePopup.helpers |
||||
isOpen: -> |
||||
Template.instance().open.get() and ((Template.instance().hasData.get() or Template.instance().data.emptyTemplate?) or not Template.instance().parentTemplate(1).subscriptionsReady()) |
||||
|
||||
data: -> |
||||
template = Template.instance() |
||||
|
||||
return template.records.get() |
@ -1,235 +0,0 @@ |
||||
@filteredUsersMemory = new Mongo.Collection null |
||||
|
||||
Meteor.startup -> |
||||
Tracker.autorun -> |
||||
if not Meteor.user()? or not Session.get('openedRoom')? |
||||
return |
||||
|
||||
filteredUsersMemory.remove({}) |
||||
messageUsers = RocketChat.models.Messages.find({rid: Session.get('openedRoom'), 'u.username': {$ne: Meteor.user().username}}, {fields: {'u.username': 1, 'u.name': 1, ts: 1}, sort: {ts: -1}}).fetch() |
||||
uniqueMessageUsersControl = {} |
||||
messageUsers.forEach (messageUser) -> |
||||
if not uniqueMessageUsersControl[messageUser.u.username]? |
||||
uniqueMessageUsersControl[messageUser.u.username] = true |
||||
filteredUsersMemory.upsert messageUser.u.username, |
||||
_id: messageUser.u.username |
||||
username: messageUser.u.username |
||||
name: messageUser.u.name |
||||
status: Session.get('user_' + messageUser.u.username + '_status') or 'offline' |
||||
ts: messageUser.ts |
||||
|
||||
|
||||
getUsersFromServer = (filter, records, cb) => |
||||
messageUsers = _.pluck(records, 'username') |
||||
Meteor.call 'spotlight', filter, messageUsers, { users: true }, (err, results) -> |
||||
if err? |
||||
return console.error err |
||||
|
||||
if results.users.length > 0 |
||||
for result in results.users |
||||
if records.length < 5 |
||||
records.push |
||||
_id: result.username |
||||
username: result.username |
||||
status: 'offline' |
||||
sort: 3 |
||||
|
||||
records = _.sortBy(records, 'sort') |
||||
|
||||
cb(records) |
||||
|
||||
getRoomsFromServer = (filter, records, cb) => |
||||
Meteor.call 'spotlight', filter, null, { rooms: true }, (err, results) -> |
||||
if err? |
||||
return console.error err |
||||
|
||||
if results.rooms.length > 0 |
||||
for room in results.rooms |
||||
if records.length < 5 |
||||
records.push room |
||||
|
||||
cb(records) |
||||
|
||||
getUsersFromServerDelayed = _.throttle getUsersFromServer, 500 |
||||
getRoomsFromServerDelayed = _.throttle getRoomsFromServer, 500 |
||||
|
||||
|
||||
Template.messagePopupConfig.helpers |
||||
popupUserConfig: -> |
||||
self = this |
||||
template = Template.instance() |
||||
|
||||
config = |
||||
title: t('People') |
||||
collection: filteredUsersMemory |
||||
template: 'messagePopupUser' |
||||
getInput: self.getInput |
||||
textFilterDelay: 200 |
||||
trigger: '@' |
||||
suffix: ' ' |
||||
getFilter: (collection, filter, cb) -> |
||||
exp = new RegExp("#{RegExp.escape filter}", 'i') |
||||
|
||||
# Get users from messages |
||||
items = filteredUsersMemory.find({ts: {$exists: true}, $or: [{username: exp}, {name: exp}]}, {limit: 5, sort: {ts: -1}}).fetch() |
||||
|
||||
# Get online users |
||||
if items.length < 5 and filter?.trim() isnt '' |
||||
messageUsers = _.pluck(items, 'username') |
||||
Meteor.users.find({$and: [{$or:[{username: exp}, {name: exp}]}, {username: {$nin: [Meteor.user()?.username].concat(messageUsers)}}]}, {limit: 5 - messageUsers.length}).fetch().forEach (item) -> |
||||
items.push |
||||
_id: item.username |
||||
username: item.username |
||||
name: item.name |
||||
status: item.status |
||||
sort: 1 |
||||
|
||||
# # Get users of room |
||||
# if items.length < 5 and filter?.trim() isnt '' |
||||
# messageUsers = _.pluck(items, 'username') |
||||
# Tracker.nonreactive -> |
||||
# roomUsernames = RocketChat.models.Rooms.findOne(Session.get('openedRoom')).usernames |
||||
# for roomUsername in roomUsernames |
||||
# if messageUsers.indexOf(roomUsername) is -1 and exp.test(roomUsername) |
||||
# items.push |
||||
# _id: roomUsername |
||||
# username: roomUsername |
||||
# status: Session.get('user_' + roomUsername + '_status') or 'offline' |
||||
# sort: 2 |
||||
|
||||
# if items.length >= 5 |
||||
# break |
||||
|
||||
# Get users from db |
||||
if items.length < 5 and filter?.trim() isnt '' |
||||
getUsersFromServerDelayed filter, items, cb |
||||
|
||||
all = |
||||
_id: 'all' |
||||
username: 'all' |
||||
system: true |
||||
name: t 'Notify_all_in_this_room' |
||||
compatibility: 'channel group' |
||||
sort: 4 |
||||
|
||||
exp = new RegExp("(^|\\s)#{RegExp.escape filter}", 'i') |
||||
if exp.test(all.username) or exp.test(all.compatibility) |
||||
items.push all |
||||
|
||||
here = |
||||
_id: 'here' |
||||
username: 'here' |
||||
system: true |
||||
name: t 'Notify_active_in_this_room' |
||||
compatibility: 'channel group' |
||||
sort: 4 |
||||
|
||||
if exp.test(here.username) or exp.test(here.compatibility) |
||||
items.push here |
||||
|
||||
return items |
||||
|
||||
getValue: (_id) -> |
||||
return _id |
||||
|
||||
return config |
||||
|
||||
popupChannelConfig: -> |
||||
self = this |
||||
template = Template.instance() |
||||
|
||||
config = |
||||
title: t('Channels') |
||||
collection: RocketChat.models.Subscriptions |
||||
trigger: '#' |
||||
suffix: ' ' |
||||
template: 'messagePopupChannel' |
||||
getInput: self.getInput |
||||
getFilter: (collection, filter, cb) -> |
||||
exp = new RegExp(filter, 'i') |
||||
|
||||
records = collection.find({name: exp, t: {$in: ['c', 'p']}}, {limit: 5, sort: {ls: -1}}).fetch() |
||||
|
||||
if records.length < 5 and filter?.trim() isnt '' |
||||
getRoomsFromServerDelayed filter, records, cb |
||||
|
||||
return records |
||||
|
||||
getValue: (_id, collection, records) -> |
||||
return _.findWhere(records, {_id: _id})?.name |
||||
|
||||
return config |
||||
|
||||
popupSlashCommandsConfig: -> |
||||
self = this |
||||
template = Template.instance() |
||||
|
||||
config = |
||||
title: t('Commands') |
||||
collection: RocketChat.slashCommands.commands |
||||
trigger: '/' |
||||
suffix: ' ' |
||||
triggerAnywhere: false |
||||
template: 'messagePopupSlashCommand' |
||||
getInput: self.getInput |
||||
getFilter: (collection, filter) -> |
||||
commands = [] |
||||
for command, item of collection |
||||
if command.indexOf(filter) > -1 |
||||
commands.push |
||||
_id: command |
||||
params: if item.params then TAPi18n.__ item.params else '' |
||||
description: TAPi18n.__ item.description |
||||
|
||||
commands = commands.sort (a, b) -> |
||||
return a._id > b._id |
||||
|
||||
commands = commands[0..10] |
||||
|
||||
return commands |
||||
|
||||
return config |
||||
|
||||
emojiEnabled: -> |
||||
return RocketChat.emoji? |
||||
|
||||
popupEmojiConfig: -> |
||||
if RocketChat.emoji? |
||||
self = this |
||||
template = Template.instance() |
||||
config = |
||||
title: t('Emoji') |
||||
collection: RocketChat.emoji.list |
||||
template: 'messagePopupEmoji' |
||||
trigger: ':' |
||||
prefix: '' |
||||
suffix: ' ' |
||||
getInput: self.getInput |
||||
getFilter: (collection, filter, cb) -> |
||||
results = [] |
||||
key = ':' + filter |
||||
|
||||
if RocketChat.emoji.packages.emojione?.asciiList[key] or filter.length < 2 |
||||
return [] |
||||
|
||||
regExp = new RegExp('^' + RegExp.escape(key), 'i') |
||||
|
||||
for key, value of collection |
||||
if results.length > 10 |
||||
break |
||||
|
||||
if regExp.test(key) |
||||
results.push |
||||
_id: key |
||||
data: value |
||||
|
||||
results.sort (a, b) -> |
||||
if a._id < b._id |
||||
return -1 |
||||
if a._id > b._id |
||||
return 1 |
||||
return 0 |
||||
|
||||
return results |
||||
|
||||
return config |
@ -1,4 +0,0 @@ |
||||
Template.messagePopupEmoji.helpers |
||||
value: -> |
||||
length = this.data.length |
||||
return this.data[length - 1] |
Loading…
Reference in new issue