2014-10-09 04:09:28 +08:00
|
|
|
|
# --------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
# If a function's last line is the statement false that represents the function returning false
|
|
|
|
|
# A function such as a click handler will continue along with the propogation and default behaivour if not stopped
|
|
|
|
|
# Returning false stops propogation/prevents default. You cannot always use the event object to call these methods
|
|
|
|
|
# Because most Meteor event handlers set the event object to the exact context of the event which does not
|
|
|
|
|
# allow you to simply call these methods.
|
|
|
|
|
# --------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
2014-08-09 00:04:04 +08:00
|
|
|
|
@sendMessage = ->
|
2014-08-15 01:20:21 +08:00
|
|
|
|
message = linkify $('#newMessageInput').val() # get the message from the input box
|
2014-08-09 00:04:04 +08:00
|
|
|
|
unless (message?.length > 0 and (/\S/.test(message))) # check the message has content and it is not whitespace
|
|
|
|
|
return # do nothing if invalid message
|
|
|
|
|
|
|
|
|
|
chattingWith = getInSession('inChatWith')
|
|
|
|
|
|
2014-09-23 03:35:53 +08:00
|
|
|
|
if chattingWith isnt "PUBLIC_CHAT"
|
2014-09-25 00:46:19 +08:00
|
|
|
|
dest = Meteor.Users.findOne(_id: chattingWith)
|
2014-08-14 02:30:55 +08:00
|
|
|
|
|
2014-08-09 00:04:04 +08:00
|
|
|
|
messageForServer = { # construct message for server
|
|
|
|
|
"message": message
|
|
|
|
|
"chat_type": if chattingWith is "PUBLIC_CHAT" then "PUBLIC_CHAT" else "PRIVATE_CHAT"
|
2014-10-04 01:34:52 +08:00
|
|
|
|
"from_userid": getInSession("DBID")
|
2014-08-09 00:04:04 +08:00
|
|
|
|
"from_username": getUsersName()
|
|
|
|
|
"from_tz_offset": "240"
|
2014-08-14 02:30:55 +08:00
|
|
|
|
"to_username": if chattingWith is "PUBLIC_CHAT" then "public_chat_username" else dest.user.name
|
2014-08-09 00:04:04 +08:00
|
|
|
|
"to_userid": if chattingWith is "PUBLIC_CHAT" then "public_chat_userid" else chattingWith
|
|
|
|
|
"from_lang": "en"
|
|
|
|
|
"from_time": getTime()
|
2014-08-19 22:10:23 +08:00
|
|
|
|
"from_color": "0x000000"
|
2014-09-23 03:35:53 +08:00
|
|
|
|
# "from_color": "0x#{getInSession("messageColor")}"
|
2014-08-09 00:04:04 +08:00
|
|
|
|
}
|
2014-08-19 22:10:23 +08:00
|
|
|
|
|
2014-10-04 01:27:24 +08:00
|
|
|
|
Meteor.call "sendChatMessagetoServer", getInSession("meetingId"), messageForServer, getInSession("userId")
|
2014-08-09 00:04:04 +08:00
|
|
|
|
$('#newMessageInput').val '' # Clear message box
|
|
|
|
|
|
|
|
|
|
Template.chatInput.events
|
2014-09-23 03:35:53 +08:00
|
|
|
|
'click #sendMessageButton': (event) ->
|
|
|
|
|
sendMessage()
|
|
|
|
|
|
|
|
|
|
'keypress #newMessageInput': (event) -> # user pressed a button inside the chatbox
|
|
|
|
|
if event.shiftKey and event.which is 13
|
2014-09-25 00:48:25 +08:00
|
|
|
|
$("#newMessageInput").append("\r") # Change newline character
|
2014-09-23 03:35:53 +08:00
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if event.which is 13 # Check for pressing enter to submit message
|
|
|
|
|
sendMessage()
|
|
|
|
|
$('#newMessageInput').val("")
|
|
|
|
|
return false
|
2014-08-09 00:04:04 +08:00
|
|
|
|
|
|
|
|
|
Template.chatInput.rendered = ->
|
|
|
|
|
$('input[rel=tooltip]').tooltip()
|
|
|
|
|
$('button[rel=tooltip]').tooltip()
|
|
|
|
|
|
2014-10-16 06:26:27 +08:00
|
|
|
|
# This method returns all messages for the user. It looks at the session to determine whether the user is in
|
|
|
|
|
#private or public chat. If true is passed, messages returned are from before the user joined. Else, the messages are from after the user joined
|
|
|
|
|
@getFormattedMessagesForChat = ->
|
|
|
|
|
friend = chattingWith = getInSession('inChatWith') # the recipient(s) of the messages
|
|
|
|
|
after = before = greeting = []
|
|
|
|
|
|
|
|
|
|
if chattingWith is 'PUBLIC_CHAT' # find all public messages
|
|
|
|
|
before = Meteor.Chat.find({'message.chat_type': chattingWith, 'message.from_time': {$lt: String(getTimeOfJoining())}}).fetch()
|
|
|
|
|
after = Meteor.Chat.find({'message.chat_type': chattingWith, 'message.from_time': {$gt: String(getTimeOfJoining())}}).fetch()
|
|
|
|
|
|
|
|
|
|
greeting = [
|
|
|
|
|
'message':
|
2014-10-16 22:47:32 +08:00
|
|
|
|
'message': getGreeting()
|
2014-10-16 06:26:27 +08:00
|
|
|
|
'from_username': 'System',
|
|
|
|
|
'from_time': getTimeOfJoining()
|
|
|
|
|
'from_color': '0x3399FF' # A nice blue in hex
|
|
|
|
|
]
|
|
|
|
|
else
|
|
|
|
|
me = getInSession("DBID")
|
|
|
|
|
after = Meteor.Chat.find({ # find all messages between current user and recipient
|
|
|
|
|
'message.chat_type': 'PRIVATE_CHAT',
|
|
|
|
|
$or: [{'message.from_userid': me, 'message.to_userid': friend},{'message.from_userid': friend, 'message.to_userid': me}]
|
|
|
|
|
}).fetch()
|
|
|
|
|
|
|
|
|
|
messages = (before.concat greeting).concat after
|
|
|
|
|
|
2014-10-16 22:47:32 +08:00
|
|
|
|
@getGreeting = ->
|
|
|
|
|
#@greeting = "Welcome to #{window.getMeetingName()}!\r\r
|
|
|
|
|
"Welcome to -------------!\r\r
|
|
|
|
|
For help on using BigBlueButton see these (short) <a href='http://www.bigbluebutton.org/videos/' target='_blank'>tutorial videos</a>.\r\r
|
|
|
|
|
To join the audio bridge click the headset icon (upper-left hand corner). Use a headset to avoid causing background noise for others.\r\r\r
|
|
|
|
|
This server is running BigBlueButton ----------------------------------.\r\r"
|
|
|
|
|
#This server is running BigBlueButton #{getInSession 'bbbServerVersion'}.\r\r"
|
2014-10-16 06:26:27 +08:00
|
|
|
|
|
|
|
|
|
Template.chatbar.helpers
|
2014-09-23 03:35:53 +08:00
|
|
|
|
getCombinedMessagesForChat: ->
|
2014-10-16 06:26:27 +08:00
|
|
|
|
msgs = getFormattedMessagesForChat()
|
2014-09-23 03:35:53 +08:00
|
|
|
|
len = msgs.length # get length of messages
|
|
|
|
|
i = 0
|
|
|
|
|
while i < len # Must be a do while, for loop compiles and stores the length of array which can change inside the loop!
|
|
|
|
|
if msgs[i].message.from_userid isnt 'System' # skip system messages
|
|
|
|
|
j = i+1 # Start looking at messages right after the current one
|
|
|
|
|
|
|
|
|
|
while j < len
|
|
|
|
|
deleted = false
|
|
|
|
|
if msgs[j].message.from_userid isnt 'System' # Ignore system messages
|
|
|
|
|
# Check if the time discrepancy between the two messages exceeds window for grouping
|
|
|
|
|
if (parseFloat(msgs[j].message.from_time)-parseFloat(msgs[i].message.from_time)) >= 60000 # 60 seconds/1 minute
|
|
|
|
|
break # Messages are too far between, so them seperated and stop joining here
|
|
|
|
|
|
|
|
|
|
if msgs[i].message.from_userid is msgs[j].message.from_userid # Both messages are from the same user
|
2014-10-11 01:49:17 +08:00
|
|
|
|
msgs[i].message.message += "\r#{msgs[j].message.message}" # Combine the messages
|
2014-09-23 03:35:53 +08:00
|
|
|
|
msgs.splice(j,1) # Delete the message from the collection
|
2014-10-08 07:09:33 +08:00
|
|
|
|
deleted = true
|
2014-09-23 03:35:53 +08:00
|
|
|
|
else break # Messages are from different people, move on
|
|
|
|
|
#
|
|
|
|
|
else break # This is the break point in the chat, don't merge
|
|
|
|
|
#
|
|
|
|
|
len = msgs.length
|
|
|
|
|
++j if not deleted
|
|
|
|
|
#
|
|
|
|
|
++i
|
|
|
|
|
len = msgs.length
|
|
|
|
|
|
|
|
|
|
msgs
|
|
|
|
|
|
2014-10-16 22:38:50 +08:00
|
|
|
|
@detectUnreadChat = ->
|
|
|
|
|
#if the current tab is not the same as the tab we just published in
|
|
|
|
|
Meteor.Chat.find({}).observe({
|
|
|
|
|
added: (chatMessage) =>
|
|
|
|
|
findDestinationTab = ->
|
|
|
|
|
if chatMessage.message?.chat_type is "PUBLIC_CHAT"
|
|
|
|
|
"PUBLIC_CHAT"
|
|
|
|
|
else
|
|
|
|
|
chatMessage.message?.from_userid
|
|
|
|
|
|
|
|
|
|
populateChatTabs() # check if we need to open a new tab
|
|
|
|
|
destinationTab = findDestinationTab()
|
|
|
|
|
if destinationTab isnt getInSession "inChatWith"
|
|
|
|
|
chatTabs.update({userId: destinationTab}, {$set: {gotMail: true}})
|
|
|
|
|
})
|
2014-09-24 08:18:27 +08:00
|
|
|
|
|
2014-09-12 00:52:33 +08:00
|
|
|
|
# When chatbar gets rendered, scroll to the bottom
|
|
|
|
|
Template.chatbar.rendered = ->
|
2014-10-16 22:38:50 +08:00
|
|
|
|
detectUnreadChat()
|
2014-09-23 03:35:53 +08:00
|
|
|
|
$('#chatbody').scrollTop($('#chatbody')[0]?.scrollHeight)
|
|
|
|
|
false
|
2014-09-12 00:26:06 +08:00
|
|
|
|
# Scrolls the message container to the bottom. The number of pixels to scroll down is the height of the container
|
|
|
|
|
Handlebars.registerHelper "autoscroll", ->
|
2014-09-23 03:35:53 +08:00
|
|
|
|
$('#chatbody').scrollTop($('#chatbody')[0]?.scrollHeight)
|
|
|
|
|
false
|
2014-07-04 01:56:16 +08:00
|
|
|
|
|
|
|
|
|
Template.optionsBar.events
|
2014-09-23 03:35:53 +08:00
|
|
|
|
'click .private-chat-user-entry': (event) -> # clicked a user's name to begin private chat
|
|
|
|
|
setInSession 'display_chatPane', true
|
2014-10-08 07:16:47 +08:00
|
|
|
|
setInSession "inChatWith", @_id
|
2014-07-10 21:11:38 +08:00
|
|
|
|
|
2014-10-09 21:45:49 +08:00
|
|
|
|
Template.optionsBar.helpers
|
|
|
|
|
thereArePeopletoChatWith: -> # Subtract 1 for the current user. Returns whether there are other people in the chat
|
|
|
|
|
# TODO: Add a check for the count to only include users who are allowed to private chat
|
|
|
|
|
(Meteor.Users.find({'meetingId': getInSession("meetingId")}).count()-1) >= 1
|
|
|
|
|
|
2014-08-16 00:26:17 +08:00
|
|
|
|
Template.optionsBar.rendered = ->
|
2014-09-23 03:35:53 +08:00
|
|
|
|
$('div[rel=tooltip]').tooltip()
|
2014-08-16 00:26:17 +08:00
|
|
|
|
|
2014-08-16 01:17:51 +08:00
|
|
|
|
Template.optionsFontSize.events
|
2014-09-23 03:35:53 +08:00
|
|
|
|
"click .fontSizeSelector": (event) ->
|
|
|
|
|
selectedFontSize = parseInt(event.target.id)
|
|
|
|
|
if selectedFontSize
|
|
|
|
|
setInSession "messageFontSize", selectedFontSize
|
|
|
|
|
else setInSession "messageFontSize", 12
|
2014-08-16 01:17:51 +08:00
|
|
|
|
|
2014-08-09 00:04:04 +08:00
|
|
|
|
Template.tabButtons.events
|
|
|
|
|
'click .close': (event) -> # user closes private chat
|
|
|
|
|
setInSession 'inChatWith', 'PUBLIC_CHAT'
|
2014-08-14 02:30:55 +08:00
|
|
|
|
setInSession 'display_chatPane', true
|
2014-09-26 01:57:58 +08:00
|
|
|
|
id = chatTabs.findOne({userId: @userId})
|
|
|
|
|
if id?
|
|
|
|
|
chatTabs.remove(id)
|
|
|
|
|
|
2014-08-09 00:04:04 +08:00
|
|
|
|
Meteor.call("deletePrivateChatMessages", getInSession("userId"), @userId)
|
2014-09-26 01:57:58 +08:00
|
|
|
|
|
2014-08-14 02:30:55 +08:00
|
|
|
|
return false # stops propogation/prevents default
|
2014-08-09 00:04:04 +08:00
|
|
|
|
|
|
|
|
|
'click .optionsChatTab': (event) ->
|
|
|
|
|
setInSession 'display_chatPane', false
|
|
|
|
|
|
|
|
|
|
'click .privateChatTab': (event) ->
|
|
|
|
|
setInSession 'display_chatPane', true
|
|
|
|
|
|
|
|
|
|
'click .publicChatTab': (event) ->
|
|
|
|
|
setInSession 'display_chatPane', true
|
|
|
|
|
|
2014-08-14 02:30:55 +08:00
|
|
|
|
'click .tab': (event) ->
|
|
|
|
|
setInSession "inChatWith", @userId
|
2014-09-26 01:24:42 +08:00
|
|
|
|
|
2014-09-26 02:35:04 +08:00
|
|
|
|
'click .gotUnreadMail': (event) ->
|
|
|
|
|
chatTabs.update({userId: @userId}, {$set: {gotMail: false}})
|
|
|
|
|
|
2014-07-09 21:18:52 +08:00
|
|
|
|
Template.tabButtons.helpers
|
|
|
|
|
makeTabButton: -> # create tab button for private chat or other such as options
|
2014-08-20 23:02:48 +08:00
|
|
|
|
safeClass = @class.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
|
|
|
safeName = @name.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
|
|
|
|
|
2014-07-10 21:11:38 +08:00
|
|
|
|
button = '<li '
|
|
|
|
|
button += 'class="'
|
2014-08-14 02:30:55 +08:00
|
|
|
|
button += 'active ' if getInSession("inChatWith") is @userId
|
2014-09-26 02:35:04 +08:00
|
|
|
|
button += 'gotUnreadMail ' if @gotMail
|
2014-10-09 04:09:28 +08:00
|
|
|
|
button += "tab #{safeClass}\"><a href=\"#\" data-toggle=\"tab\" id=\"#{safeName}\" >#{safeName}"
|
2014-08-14 22:48:08 +08:00
|
|
|
|
button += ' <button class="close closeTab" type="button" >×</button>' if @class is 'privateChatTab'
|
2014-07-09 21:18:52 +08:00
|
|
|
|
button += '</a></li>'
|
|
|
|
|
button
|
2014-07-07 23:30:17 +08:00
|
|
|
|
|
2014-10-16 22:38:50 +08:00
|
|
|
|
@activateBreakLines = (str) ->
|
|
|
|
|
res = str?.replace? /\\n/gim, '<br/>'
|
|
|
|
|
res = res?.replace? /\r/gim, '<br/>'
|
2014-09-23 03:35:53 +08:00
|
|
|
|
|
2014-10-16 22:38:50 +08:00
|
|
|
|
# make links received from Flash client clickable in HTML
|
|
|
|
|
@toClickable = (str) ->
|
|
|
|
|
res = str?.replace? /<a href='event:/gim, "<a target='_blank' href='"
|
|
|
|
|
res = res?.replace? /<a href="event:/gim, '<a target="_blank" href="'
|
|
|
|
|
|
|
|
|
|
Template.message.helpers
|
2014-09-23 03:35:53 +08:00
|
|
|
|
toClockTime: (epochTime) ->
|
|
|
|
|
if epochTime is null
|
|
|
|
|
return ""
|
|
|
|
|
local = new Date()
|
|
|
|
|
offset = local.getTimezoneOffset()
|
|
|
|
|
epochTime = epochTime - offset * 60000 # 1 min = 60 s = 60,000 ms
|
|
|
|
|
dateObj = new Date(epochTime)
|
|
|
|
|
hours = dateObj.getUTCHours()
|
|
|
|
|
minutes = dateObj.getUTCMinutes()
|
|
|
|
|
if minutes < 10
|
|
|
|
|
minutes = "0" + minutes
|
|
|
|
|
hours + ":" + minutes
|
|
|
|
|
|
|
|
|
|
sanitizeAndFormat: (str) ->
|
2014-10-16 22:38:50 +08:00
|
|
|
|
if str?
|
|
|
|
|
# First, replace replace all tags with the ascii equivalent (excluding those involved in anchor tags)
|
|
|
|
|
res = str.replace?(/&/g, '&').replace?(/<(?![au\/])/g, '<').replace?(/\/([^au])>/g, '$1>').replace?(/([^=])"(?!>)/g, '$1"');
|
|
|
|
|
|
|
|
|
|
res = toClickable res
|
|
|
|
|
res = activateBreakLines res
|