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
|
2014-11-06 12:51:01 +08:00
|
|
|
# Because most Meteor event handlers set the event object to the exact context of the event which does not
|
2014-10-09 04:09:28 +08:00
|
|
|
# allow you to simply call these methods.
|
|
|
|
# --------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
2014-10-28 22:29:11 +08:00
|
|
|
@activateBreakLines = (str) ->
|
|
|
|
if typeof str is 'string'
|
2015-02-12 04:06:19 +08:00
|
|
|
# turn '\r' carriage return characters into '<br/>' break lines
|
2015-02-12 03:43:46 +08:00
|
|
|
res = str.replace(new RegExp(CARRIAGE_RETURN, 'g'), BREAK_LINE)
|
|
|
|
res
|
2014-09-23 03:35:53 +08:00
|
|
|
|
2014-10-28 22:29:11 +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
|
2014-12-01 10:39:33 +08:00
|
|
|
Tracker.autorun (comp) ->
|
2015-06-25 08:21:50 +08:00
|
|
|
tabsTime = getInSession('userListRenderedTime')
|
2014-12-20 01:23:24 +08:00
|
|
|
if tabsTime? and chatMessage.message.from_userid isnt "SYSTEM_MESSAGE" and chatMessage.message.from_time - tabsTime > 0
|
2015-06-25 08:21:50 +08:00
|
|
|
populateNotifications(chatMessage) # check if we need to show a new notification
|
2014-12-20 01:23:24 +08:00
|
|
|
destinationTab = findDestinationTab()
|
|
|
|
if destinationTab isnt getInSession "inChatWith"
|
2015-06-25 08:21:50 +08:00
|
|
|
setInSession 'chats', getInSession('chats').map((tab) ->
|
2015-07-11 04:42:10 +08:00
|
|
|
if tab.userId is destinationTab
|
|
|
|
tab.gotMail = true
|
|
|
|
tab.number++
|
2014-12-20 01:23:24 +08:00
|
|
|
tab
|
|
|
|
)
|
|
|
|
comp.stop()
|
2014-10-28 22:29:11 +08:00
|
|
|
})
|
2014-08-09 00:04:04 +08:00
|
|
|
|
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
|
2014-10-28 22:29:11 +08:00
|
|
|
# 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
|
2014-10-16 06:26:27 +08:00
|
|
|
@getFormattedMessagesForChat = ->
|
2014-12-17 08:20:13 +08:00
|
|
|
chattingWith = getInSession('inChatWith')
|
|
|
|
if chattingWith is 'PUBLIC_CHAT' # find all public and system messages
|
2014-12-17 08:29:58 +08:00
|
|
|
return Meteor.Chat.find({'message.chat_type': $in: ["SYSTEM_MESSAGE","PUBLIC_CHAT"]},{sort: {'message.from_time': 1}}).fetch()
|
2014-10-16 06:26:27 +08:00
|
|
|
else
|
2015-05-20 00:06:42 +08:00
|
|
|
return Meteor.Chat.find({'message.chat_type': 'PRIVATE_CHAT', $or: [{'message.to_userid': chattingWith},{'message.from_userid': chattingWith}]}).fetch()
|
2014-10-16 06:26:27 +08:00
|
|
|
|
2014-10-28 22:29:11 +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", ->
|
|
|
|
$('#chatbody').scrollTop($('#chatbody')[0]?.scrollHeight)
|
|
|
|
false
|
|
|
|
|
2015-04-01 01:25:05 +08:00
|
|
|
# true if the lock settings limit public chat and the current user is locked
|
2015-03-31 06:48:25 +08:00
|
|
|
Handlebars.registerHelper "publicChatDisabled", ->
|
|
|
|
userIsLocked = Meteor.Users.findOne({userId:getInSession 'userId'})?.user.locked
|
|
|
|
publicChatIsDisabled = Meteor.Meetings.findOne({})?.roomLockSettings.disablePubChat
|
2015-04-01 02:42:42 +08:00
|
|
|
presenter = Meteor.Users.findOne({userId:getInSession 'userId'})?.user.presenter
|
|
|
|
return userIsLocked and publicChatIsDisabled and !presenter
|
2015-03-31 06:48:25 +08:00
|
|
|
|
2015-04-01 01:25:05 +08:00
|
|
|
# true if the lock settings limit private chat and the current user is locked
|
|
|
|
Handlebars.registerHelper "privateChatDisabled", ->
|
|
|
|
userIsLocked = Meteor.Users.findOne({userId:getInSession 'userId'})?.user.locked
|
|
|
|
privateChatIsDisabled = Meteor.Meetings.findOne({})?.roomLockSettings.disablePrivChat
|
2015-04-01 02:42:42 +08:00
|
|
|
presenter = Meteor.Users.findOne({userId:getInSession 'userId'})?.user.presenter
|
|
|
|
return userIsLocked and privateChatIsDisabled and !presenter
|
2015-04-01 01:25:05 +08:00
|
|
|
|
2015-05-20 00:06:42 +08:00
|
|
|
# return whether the user's chat pane is open in Private chat
|
2015-04-01 01:25:05 +08:00
|
|
|
Handlebars.registerHelper "inPrivateChat", ->
|
2015-05-20 00:06:42 +08:00
|
|
|
return (getInSession 'inChatWith') isnt 'PUBLIC_CHAT'
|
2015-04-01 01:25:05 +08:00
|
|
|
|
2014-10-28 22:29:11 +08:00
|
|
|
@sendMessage = ->
|
|
|
|
message = linkify $('#newMessageInput').val() # get the message from the input box
|
|
|
|
unless (message?.length > 0 and (/\S/.test(message))) # check the message has content and it is not whitespace
|
|
|
|
return # do nothing if invalid message
|
|
|
|
|
2015-05-06 04:15:33 +08:00
|
|
|
color = "0x000000" #"0x#{getInSession("messageColor")}"
|
|
|
|
if (chattingWith = getInSession('inChatWith')) isnt "PUBLIC_CHAT"
|
2014-11-29 00:40:14 +08:00
|
|
|
toUsername = Meteor.Users.findOne(userId: chattingWith)?.user.name
|
2015-05-06 04:15:33 +08:00
|
|
|
BBB.sendPrivateChatMessage(color, "en", message, chattingWith, toUsername)
|
|
|
|
else
|
|
|
|
BBB.sendPublicChatMessage(color, "en", message)
|
2014-11-27 06:49:21 +08:00
|
|
|
|
2014-10-28 22:29:11 +08:00
|
|
|
$('#newMessageInput').val '' # Clear message box
|
|
|
|
|
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-12-17 08:20:13 +08:00
|
|
|
len = msgs?.length # get length of messages
|
2014-09-23 03:35:53 +08:00
|
|
|
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
|
2015-02-12 04:06:19 +08:00
|
|
|
# insert a '\r' carriage return character between messages to put them on a new line
|
2015-02-12 03:43:46 +08:00
|
|
|
msgs[i].message.message += "#{CARRIAGE_RETURN}#{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-12-18 05:09:12 +08:00
|
|
|
userExists: ->
|
2015-05-20 00:06:42 +08:00
|
|
|
if getInSession('inChatWith') is "PUBLIC_CHAT"
|
2014-12-18 05:09:12 +08:00
|
|
|
return true
|
|
|
|
else
|
|
|
|
return Meteor.Users.findOne({userId: getInSession('inChatWith')})?
|
|
|
|
|
2014-12-20 01:23:24 +08:00
|
|
|
# When chatbar gets rendered, launch the auto-check for unread chat
|
2015-07-17 07:01:54 +08:00
|
|
|
Template.chatbar.rendered = ->
|
|
|
|
detectUnreadChat()
|
2014-12-20 01:23:24 +08:00
|
|
|
|
2015-07-22 04:59:25 +08:00
|
|
|
# When "< Public" is clicked, go to public chat
|
2015-05-21 08:47:25 +08:00
|
|
|
Template.chatbar.events
|
|
|
|
'click .toPublic': (event) ->
|
|
|
|
setInSession 'inChatWith', 'PUBLIC_CHAT'
|
2015-07-04 02:06:40 +08:00
|
|
|
setInSession 'chats', getInSession('chats').map((chat) ->
|
2015-07-11 04:42:10 +08:00
|
|
|
if chat.userId is "PUBLIC_CHAT"
|
2015-07-22 04:59:25 +08:00
|
|
|
chat.gotMail = false
|
2015-07-11 04:42:10 +08:00
|
|
|
chat.number = 0
|
2015-07-04 02:06:40 +08:00
|
|
|
chat
|
|
|
|
)
|
2015-05-21 08:47:25 +08:00
|
|
|
|
2015-06-16 04:19:55 +08:00
|
|
|
Template.privateChatTab.rendered = ->
|
|
|
|
if isLandscape() or isPortrait()
|
|
|
|
$("#newMessageInput").focus()
|
|
|
|
|
2014-12-20 01:23:24 +08:00
|
|
|
# When message gets rendered, scroll to the bottom
|
|
|
|
Template.message.rendered = ->
|
2014-09-23 03:35:53 +08:00
|
|
|
$('#chatbody').scrollTop($('#chatbody')[0]?.scrollHeight)
|
|
|
|
false
|
2014-10-28 22:29:11 +08:00
|
|
|
|
2015-07-20 08:34:07 +08:00
|
|
|
Template.chatInput.rendered = ->
|
|
|
|
$('.panel-footer').resizable
|
|
|
|
handles: 'n'
|
|
|
|
minHeight: 70
|
|
|
|
resize: (event, ui) ->
|
|
|
|
if $('.panel-footer').css('top') is '0px'
|
|
|
|
$('.panel-footer').height(70) # prevents the element from shrinking vertically for 1-2 px
|
2015-07-21 06:23:51 +08:00
|
|
|
else
|
|
|
|
$('.panel-footer').css('top', parseInt($('.panel-footer').css('top')) + 1 + 'px')
|
2015-07-20 08:34:07 +08:00
|
|
|
$('#chatbody').height($('#chat').height() - $('.panel-footer').height() - 45)
|
|
|
|
$('#chatbody').scrollTop($('#chatbody')[0]?.scrollHeight)
|
|
|
|
start: (event, ui) ->
|
2015-07-21 06:23:51 +08:00
|
|
|
$('#newMessageInput').css('overflow', '')
|
2015-07-20 08:34:07 +08:00
|
|
|
$('.panel-footer').resizable('option', 'maxHeight', Math.max($('.panel-footer').height(), $('#chat').height() / 2))
|
2015-07-21 06:23:51 +08:00
|
|
|
stop: (event, ui) ->
|
2015-07-22 04:59:25 +08:00
|
|
|
setInSession 'chatInputMinHeight', $('.panel-footer').height() + 1
|
2015-07-20 08:34:07 +08:00
|
|
|
|
2014-10-28 22:29:11 +08:00
|
|
|
Template.chatInput.events
|
|
|
|
'click #sendMessageButton': (event) ->
|
2014-12-20 07:51:31 +08:00
|
|
|
$('#sendMessageButton').blur()
|
2014-10-28 22:29:11 +08:00
|
|
|
sendMessage()
|
2015-07-22 04:59:25 +08:00
|
|
|
adjustChatInputHeight()
|
2014-10-28 22:29:11 +08:00
|
|
|
|
|
|
|
'keypress #newMessageInput': (event) -> # user pressed a button inside the chatbox
|
2014-12-16 23:11:23 +08:00
|
|
|
key = (if event.charCode then event.charCode else (if event.keyCode then event.keyCode else 0))
|
2014-12-16 22:43:03 +08:00
|
|
|
|
|
|
|
if event.shiftKey and (key is 13)
|
2014-12-16 23:11:23 +08:00
|
|
|
event.preventDefault()
|
2015-02-12 04:06:19 +08:00
|
|
|
# append a '\r' carriage return character to the input box dropping the cursor to a new line
|
2015-02-12 03:43:46 +08:00
|
|
|
document.getElementById("newMessageInput").value += CARRIAGE_RETURN # Change newline character
|
2014-10-28 22:29:11 +08:00
|
|
|
return
|
2014-11-06 12:51:01 +08:00
|
|
|
|
2014-12-16 22:43:03 +08:00
|
|
|
if key is 13 # Check for pressing enter to submit message
|
2014-12-16 23:11:23 +08:00
|
|
|
event.preventDefault()
|
2014-10-28 22:29:11 +08:00
|
|
|
sendMessage()
|
|
|
|
$('#newMessageInput').val("")
|
|
|
|
return false
|
2015-07-22 05:47:05 +08:00
|
|
|
|
|
|
|
Template.chatInputControls.rendered = ->
|
|
|
|
$('#newMessageInput').on('keydown paste cut', () -> setTimeout(() ->
|
|
|
|
adjustChatInputHeight()
|
|
|
|
, 0))
|
2014-10-28 22:29:11 +08:00
|
|
|
|
|
|
|
Template.message.helpers
|
|
|
|
sanitizeAndFormat: (str) ->
|
|
|
|
if typeof str is 'string'
|
|
|
|
# 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
|
|
|
|
|
|
|
|
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
|
2014-07-04 01:56:16 +08:00
|
|
|
|
2014-08-16 01:17:51 +08:00
|
|
|
Template.optionsFontSize.events
|
2015-03-17 21:45:49 +08:00
|
|
|
"click #decreaseFontSize": (event) ->
|
|
|
|
if getInSession("messageFontSize") is 8 # min
|
|
|
|
$('#decreaseFontSize').disabled = true
|
2015-05-07 06:08:49 +08:00
|
|
|
$('#decreaseFontSize').removeClass('icon fi-minus')
|
2015-03-17 21:45:49 +08:00
|
|
|
$('#decreaseFontSize').html('MIN')
|
2015-03-05 05:33:37 +08:00
|
|
|
else
|
2015-03-17 21:45:49 +08:00
|
|
|
setInSession "messageFontSize", getInSession("messageFontSize") - 2
|
|
|
|
if $('#increaseFontSize').html() is 'MAX'
|
|
|
|
$('#increaseFontSize').html('')
|
2015-05-07 06:08:49 +08:00
|
|
|
$('#increaseFontSize').addClass('icon fi-plus')
|
2015-03-17 21:45:49 +08:00
|
|
|
|
|
|
|
"click #increaseFontSize": (event) ->
|
|
|
|
if getInSession("messageFontSize") is 40 # max
|
|
|
|
$('#increaseFontSize').disabled = true
|
2015-05-07 06:08:49 +08:00
|
|
|
$('#increaseFontSize').removeClass('icon fi-plus')
|
2015-03-17 21:45:49 +08:00
|
|
|
$('#increaseFontSize').html('MAX')
|
|
|
|
else
|
|
|
|
setInSession "messageFontSize", getInSession("messageFontSize") + 2
|
|
|
|
if $('#decreaseFontSize').html() is 'MIN'
|
|
|
|
$('#decreaseFontSize').html('')
|
2015-05-07 06:08:49 +08:00
|
|
|
$('#decreaseFontSize').addClass('icon fi-minus')
|
2015-02-05 02:16:35 +08:00
|
|
|
|
2014-10-16 22:38:50 +08:00
|
|
|
# make links received from Flash client clickable in HTML
|
|
|
|
@toClickable = (str) ->
|
2014-10-16 23:11:09 +08:00
|
|
|
if typeof str is 'string'
|
|
|
|
res = str.replace /<a href='event:/gim, "<a target='_blank' href='"
|
|
|
|
res = res.replace /<a href="event:/gim, '<a target="_blank" href="'
|